#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //connect(ui.quitButton, SIGNAL(clicked()), this, SLOT(close()));

    //First, set up our program
    //Initialize(1);

    settings = 0;
    dRetraction = 0;
    nRetractCount = 0;
    nResetCount = 0;

    //initialize to 0 eventually here
    mNationalInstruments = new NationalInstruments(this);
    mTrinamic = new TrinamicCommunication();
    mMatroxImagingLibrary = new MatroxImagingLibrary();
    pw = new PlotWindow(this);
    pw->setStyle(style());
    pw->setPalette(palette());
    bRunningScript = false;
    bInitialized = false;

    bAcquiringMosaic = false;
    bStackPreciseReady = false;
    bTaskStopMonitor = false;
    bTaskStartMonitor = false;
    bTaskStopAcquire = false;
    bTaskStartAcquire = false;
    bTaskUpdateUi = false;

}

MainWindow::~MainWindow()
{
    Shutdown();


    //only delete variables here.
    //shutdown handles other shutdown issues

    delete ui;

    if (settings) delete settings;
    if (mNationalInstruments) delete mNationalInstruments;
    if (mTrinamic) delete mNationalInstruments;
    if (mMatroxImagingLibrary) delete mNationalInstruments;
    if (pw) delete pw;

    QString logFile("run_log.txt");
    //fclose(logFile.toLocal8Bit().data());
}

void MainWindow::Initialize()
{

    printf("Starting program output: \n");
    printf("Version %d\n", MULTIPHOTON_VERSION);

    pw->Initialize();
    pw->show();
    pw->hide();
    for(int i=0;i<24;i++)
    plotvector[i].resize(200);
    plotvectorx.resize(200);
    for(int i=0;i<200;i++) plotvectorx[i] = i;

    for(int i=0;i<3;i++)
    plothistogram[i].resize(HIST_VALUE);

    plothistogramx.resize(HIST_VALUE);
    for(int i=0;i<HIST_VALUE;i++)
        plothistogramx[i] = i;


    #include <cstdio>
    QString logFile("run_log.txt");
    //freopen(logFile.toLocal8Bit().data(), "w", stdout);

    QCoreApplication::setApplicationName("Multiphoton");
    QCoreApplication::setApplicationVersion("1.0");
    QCoreApplication::setOrganizationName("BSD");

    qDebugLog.setFileName("multiphoton_log.txt");
    qDebugLog.open(QIODevice::WriteOnly | QIODevice::Append);
    QDebug(QtDebugMsg) << "Start debug output" << endl;

    //SETUP GLOBAL KEYBOARD MONITORING
    SystemKeyboardReadWrite::instance()->setConnected(true);
    QObject::connect(SystemKeyboardReadWrite::instance(), SIGNAL(keyPressed(QKeyEvent*,bool)),
                          this, SLOT(OnKeyPressed(QKeyEvent*,bool)));

    QObject::connect(SystemKeyboardReadWrite::instance(), SIGNAL(shuttleMoved(DWORD,UCHAR,WORD,WORD)),
                     this, SLOT(OnShuttleMoved(DWORD,UCHAR,WORD,WORD)));

    QDebug(QtDebugMsg) << "Keyboard hook." << endl;

    //DEFAULT KEYS

    nKeymap[KEY_XPOS] = Qt::Key_D;
    nKeymap[KEY_XNEG] = Qt::Key_A;
    nKeymap[KEY_YPOS] = Qt::Key_W;
    nKeymap[KEY_YNEG] = Qt::Key_S;
    nKeymap[KEY_ZPOS] = Qt::Key_BracketRight;
    nKeymap[KEY_ZNEG] = Qt::Key_BracketLeft;
    nKeymap[KEY_TPOS] = Qt::Key_Equal;
    nKeymap[KEY_TNEG] = Qt::Key_Minus;
    nKeymap[KEY_TTPOS] = Qt::Key_0;
    nKeymap[KEY_TTNEG] = Qt::Key_9;

    nKeymap[KEY_XWHEELPOS] = Qt::Key_H;
    nKeymap[KEY_XWHEELNEG] = Qt::Key_F;
    nKeymap[KEY_YWHEELPOS] = Qt::Key_T;
    nKeymap[KEY_YWHEELNEG] = Qt::Key_G;
    nKeymap[KEY_ZWHEELPOS] = Qt::Key_U;
    nKeymap[KEY_ZWHEELNEG] = Qt::Key_Y;
    nKeymap[KEY_TWHEELPOS] = Qt::Key_6;
    nKeymap[KEY_TWHEELNEG] = Qt::Key_7;

    LoadSettings();

    mNationalInstruments->bResonantScanning = false;

    //Trinamic initialization, including comm port open etc
    if(bTrinamic)
    {
        InitializeTrinamic(true);
    }

    if(bNationalInstruments)
    {
        printf("Initializing NI cards\n");
        mNationalInstruments->Initialize();
    }
    if(bResonantScanning)
    {
        if(bMatrox)
        {
            printf("Initializing Matrox\n");
            //printf("Initializing matrox board\n");
            //system with matrox board (perhaps standard scanning compatible in future)
            mMatroxImagingLibrary->nDesiredLinesPerFrame = mNationalInstruments->nLinesPerFrame;
            mMatroxImagingLibrary->Initialize();
            mMatroxImagingLibrary->UpdateLUT();
            mMatroxImagingLibrary->UpdateCouplingMode();
            mMatroxImagingLibrary->UpdateGain();
        }

    }
    else
    {
        //compact view for just motors
        printf("Resizing view\n");
        this->resize(QSize(1160,240));
        ui->tab_stack->setDisabled(true);
    }

    //Finally, set up UI
    UpdateInterface();

   //Stack acquisition signal connection
    //in the future, this should be a generic scriptable timer
   connect(&mTimerStack, SIGNAL(timeout()), SLOT(ZStackTakeNextStep()));
   connect(&mTimerScript, SIGNAL(timeout()), SLOT(ScriptEngine()));
   connect(&mTimerTasks, SIGNAL(timeout()), SLOT(TimerTasks()));
   //mTimerTasks.setInterval(300);

   printf("Started task timer - 300ms\n");
   mTimerTasks.start(300);

   bAcquiringStack = false;
   bAcquiringStack_Precise = false;

   //Shuttle controller timer
   //mTimerShuttle.get

   //Initialize Camera object
   // mCamera.Initialize(this->winId());

   this->show();

   bInitialized = true;

}

void MainWindow::Shutdown()
{

    printf("Shutdown: Starting Shutdown.\n");

    mNationalInstruments->CloseShutter(0);
    MoveFirgelli(0,0);

    mNationalInstruments->Shutdown();
    mMatroxImagingLibrary->Shutdown();

    if(mTimerPosition.isActive())
    {
        printf("Shutdown: Stopping position query.\n");
        mTimerPosition.stop();
    }

    SystemKeyboardReadWrite::instance()->setConnected(false);
    printf("Shutdown: Released keyboard.\n");

    if( bTrinamic)
    {
        printf("Shutdown: Closing motor control.\n");
        ShutdownTrinamic();
    }

    qDebugLog.close();
    printf("Shutdown: Closed debug log.\n");

    SaveSettings();
    printf("Shutdown: Saved settings.\n");

}

void MainWindow::InitializeTrinamic(bool ShutdownOnFail)
{
    printf("Initializing trinamic board\n");

    //LOOP TO CHECK ALL BAUDRATES, AND SELECT THE CORRECT ONE
    //THEN SAVE THE DESIRED BAUDRATE TO THE BOARD PERMANENTLY
    bCommPortOpen = false;

    bool bFoundTrinamic = false;

    /*

    0 9600 baud efault
    1 14400 baud
      2  19200 baud
     3  28800 baud
      4  38400 baud
      5  57600 baud
      6  76800 baud Not supported by Windows!
     7  (115200 baud)

            */
    int setbaudrate = 5;

    int nBaudrates[3] = {9600, 57600, 115200};
    for(int i = 0; i < 3; i++)
    {
        printf("Trying baudrate %d...\n",nBaudrates[i]);

        mTrinamic->hTrinamicSerial = OpenSerial(L"COM1",nBaudrates[i]);
        int error = mTrinamic->CheckTrinamic();
        if (error == 0)
        {
            bFoundTrinamic = true;
            printf("Established comm.\n");
            mTrinamic->SetBaudrate(setbaudrate);  //0-9600 5-57600 7-115200
            break;
        }
        else
        {
            bFoundTrinamic = false;
            printf("Wrong baudrate or comm error. Retry.\n");
            CloseSerial(mTrinamic->hTrinamicSerial);
            mTrinamic->hTrinamicSerial = 0;
        }
    }

    if(ShutdownOnFail)
    {
        if(mTrinamic->hTrinamicSerial == 0)
        {
            printf("Fatal error: Could not communicate with motor controller (at any baudrate)\n.");
            printf("Please check that the motor controller PSU is on, and that the data cable is connected.\n");
            printf("Goodbye (5 seconds until shutdown)...\n");
            Sleep(5000);
            this->close();
        }
    }

    //Initialize Trinamic object
    mTrinamic->qSettings = settings;

    //Look for trinamic board
    //mTrinamic->CheckTrinamic();

    //Initialize trinamic
    mTrinamic->Initialize();

    //mTrinamic->hMainWindow = this;

    settings->beginGroup("Trinamic");

    printf("Starting Trinamic position query timer - %d ms\n.", settings->value("position_refresh_interval_ms").toInt());
    connect(&mTimerPosition, SIGNAL(timeout()), SLOT(PositionQuery()));
    mTimerPosition.start(settings->value("position_refresh_interval_ms").toInt());
    settings->endGroup();

}

void MainWindow::ShutdownTrinamic()
{
    if(bCommPortOpen)
    {
        printf("Shutting down serial port\n");
        CloseSerial(mTrinamic->hTrinamicSerial);
        mTrinamic->hTrinamicSerial = 0;
        bCommPortOpen = false;
    }
    else
    {
        printf("No need to shut off serial port.\n");
    }
}

void MainWindow::LoadSettings()
{

    if(settings)
    {
        delete settings;
        settings = 0;
    }

    settings = new QSettings("multiphoton.ini",QSettings::IniFormat);

    if(settings->contains("settings"))
    //if(0)
    {
        printf("Found settings file.\n");
        //settings exists.  super duper.
        //need way to detect incorrect settings.

        //initialize panel configuration
        bNationalInstruments = settings->value("nationalinstruments").toBool();
        bTrinamic            = settings->value("trinamic").toBool();
        bMatrox              = settings->value("matrox").toBool();
        bResonantScanning    = settings->value("resonantscanning").toBool();

        nMotionSettleMillseconds = 1000;
        nMotionSettleMillseconds = settings->value("motion_settle_ms").toInt();
        nAcquisitionTimeMilliseconds = 3000;
        nAcquisitionTimeMilliseconds = settings->value("slice_acquisition_time_ms").toInt();

        //Trinamic initialization, including comm port open etc
        if(bTrinamic)
        {
            settings->beginGroup("Trinamic");

            mTrinamic->bRotationMode = settings->value("rotation_mode").toBool();
            mTrinamic->bMotorizedRotation = settings->value("motorized_rotation").toBool();
            dRetraction = settings->value("retraction_mm").toInt();

            settings->endGroup();

        }
        else
        {
            //disable the trinamic box
        }



        if(bNationalInstruments)
        {

            settings->beginGroup("NationalInstruments");

            //cut and paste from initialize, overridden by settings file
            mNationalInstruments->bResonantScanning = false;
            mNationalInstruments->nLinesPerFrame          = settings->value("lines_per_frame").toInt();
            mNationalInstruments->dFastFreq          = settings->value("fastfreq").toDouble();

            mNationalInstruments->dFastBlankWidth          = settings->value("fastwidth").toDouble();
            mNationalInstruments->dFastBlankDelay         = settings->value("fastdelay").toDouble();
            mNationalInstruments->dSlowBlankWidth          = settings->value("slowwidth").toDouble();
            mNationalInstruments->dSlowBlankDelay          = settings->value("slowdelay").toDouble();


            mNationalInstruments->nEdgeWidth          = settings->value("hblank_duration").toInt();

            mNationalInstruments->nPulseDelay             = settings->value("fastaxis_pulsedelay").toInt();
            mNationalInstruments->nPulseDelay1x             = settings->value("fastaxis_pulsedelay_1x").toInt();
            mNationalInstruments->nPulseDelay2x             = settings->value("fastaxis_pulsedelay_2x").toInt();
            mNationalInstruments->nPulseDelay4x             = settings->value("fastaxis_pulsedelay_4x").toInt();
            mNationalInstruments->nPulseDelay8x             = settings->value("fastaxis_pulsedelay_8x").toInt();
            mNationalInstruments->nPulseDelay16x             = settings->value("fastaxis_pulsedelay_16x").toInt();
            mNationalInstruments->nPulseDelay32x             = settings->value("fastaxis_pulsedelay_32x").toInt();
            mNationalInstruments->nPulseDelay64x             = settings->value("fastaxis_pulsedelay_64x").toInt();

            mNationalInstruments->dFastFreq1x             = settings->value("fastaxis_fastfreq_1x").toDouble();
            mNationalInstruments->dFastFreq2x             = settings->value("fastaxis_fastfreq_2x").toDouble();
            mNationalInstruments->dFastFreq4x             = settings->value("fastaxis_fastfreq_4x").toDouble();
            mNationalInstruments->dFastFreq8x             = settings->value("fastaxis_fastfreq_8x").toDouble();
            mNationalInstruments->dFastFreq16x             = settings->value("fastaxis_fastfreq_16x").toDouble();
            mNationalInstruments->dFastFreq32x             = settings->value("fastaxis_fastfreq_32x").toDouble();

            mNationalInstruments->dFastBlankDelay1x             = settings->value("fastaxis_fastblankdelay_1x").toDouble();
            mNationalInstruments->dFastBlankDelay2x             = settings->value("fastaxis_fastblankdelay_2x").toDouble();
            mNationalInstruments->dFastBlankDelay4x             = settings->value("fastaxis_fastblankdelay_4x").toDouble();
            mNationalInstruments->dFastBlankDelay8x             = settings->value("fastaxis_fastblankdelay_8x").toDouble();
            mNationalInstruments->dFastBlankDelay16x             = settings->value("fastaxis_fastblankdelay_16x").toDouble();
            mNationalInstruments->dFastBlankDelay32x             = settings->value("fastaxis_fastblankdelay_32x").toDouble();



            mNationalInstruments->dYScanAmplitudeVolts    = settings->value("slowaxis_amplitude_volts").toDouble();
            mNationalInstruments->dYScanOffsetVolts       = settings->value("slowaxis_offset_volts").toDouble();
            mNationalInstruments->dYScanFraction          = settings->value("slowaxis_scanfraction").toDouble();
            mNationalInstruments->dXResonanceFrequency    = settings->value("fastaxis_resonantfrequency").toInt(); //approx (bounds?)
            mNationalInstruments->dXScanAmplitudeVolts    = settings->value("fastaxis_amplitude_volts").toDouble();
            mNationalInstruments->dXScanFraction          = settings->value("fastaxis_scanfraction").toDouble();
            mNationalInstruments->nActuatorPinoutVersion  = settings->value("actuator_pinout_version").toInt();
            mNationalInstruments->bFastBlank            = settings->value("fastblank").toBool();
            mNationalInstruments->bSlowBlank            = settings->value("slowblank").toBool();
            mNationalInstruments->dLaserPower          = settings->value("laserpower").toDouble();
            mNationalInstruments->dYRampDutyCycle       = 1.0 - settings->value("slowaxis_flybackfraction").toDouble();

            mMatroxImagingLibrary->nResonantFrequency = int(mNationalInstruments->dXResonanceFrequency);

            settings->endGroup();
        }
        else
        {
        }

        if(bResonantScanning)
        {
            //resonant scanning system

        }
        else
        {
            //This is a standard scanning system, disable scanning panels
        }

        if(bMatrox)
        {
            //printf("Initializing matrox board\n");
            //system with matrox board (perhaps standard scanning compatible in future)
            mMatroxImagingLibrary->nDesiredLinesPerFrame = mNationalInstruments->nLinesPerFrame;

            settings->beginGroup("Matrox");

            mMatroxImagingLibrary->mhz =    settings->value("adc_mhz").toInt();
            mMatroxImagingLibrary->bSaveChannel[0]          = settings->value("save_channel_1").toBool();
            mMatroxImagingLibrary->bSaveChannel[1]          = settings->value("save_channel_2").toBool();
            mMatroxImagingLibrary->bSaveChannel[2]          = settings->value("save_channel_3").toBool();
            mMatroxImagingLibrary->nFragmentSize          = settings->value("fragment_size").toInt();
            mMatroxImagingLibrary->bFragment          = settings->value("fragment").toBool();
            mMatroxImagingLibrary->bACCoupling          = settings->value("ac_coupling").toBool();
            mMatroxImagingLibrary->bCompGBRatio          = settings->value("compute_bluegreen_ratio").toBool();
            mMatroxImagingLibrary->bCompHistograms          = settings->value("compute_histograms").toBool();
            mMatroxImagingLibrary->bCompTraces          = settings->value("compute_traces").toBool();
            mMatroxImagingLibrary->bExtTrigger          = settings->value("external_trigger").toBool();
            mMatroxImagingLibrary->bFlipRes          = settings->value("flip_res").toBool();
            mMatroxImagingLibrary->bFlipSlow          = settings->value("flip_slow").toBool();
            mMatroxImagingLibrary->bFlipX          = settings->value("flip_x").toBool();
            mMatroxImagingLibrary->bFlipY          = settings->value("flip_y").toBool();
            mMatroxImagingLibrary->bInvert          = settings->value("invert").toBool();
            mMatroxImagingLibrary->bLog          = settings->value("log").toBool();
            mMatroxImagingLibrary->bMeanConvolve          = settings->value("mean").toBool();
            mMatroxImagingLibrary->bMedianConvolve          = settings->value("median").toBool();
            mMatroxImagingLibrary->bOvCrosshairs          = settings->value("overlay_crosshairs").toBool();
            mMatroxImagingLibrary->bOverlay          = settings->value("overlay").toBool();
            mMatroxImagingLibrary->bOvExposure          = settings->value("overlay_exposure").toBool();
            mMatroxImagingLibrary->bOvFramenumber          = settings->value("overlay_framenumber").toBool();
            mMatroxImagingLibrary->bOvLiveGrid          = settings->value("overlay_livegrid").toBool();
            mMatroxImagingLibrary->bOvOverlayImage          = settings->value("overlay_image").toBool();
            mMatroxImagingLibrary->bOvPosition          = settings->value("overlay_position").toBool();
            mMatroxImagingLibrary->bOvScalebars          = settings->value("overlay_scalebars").toBool();
            mMatroxImagingLibrary->bRetrigger          = settings->value("retrigger").toBool();
            mMatroxImagingLibrary->bWarp          = settings->value("sine_warp").toBool();
            mMatroxImagingLibrary->dFOVXMicrons          = settings->value("fov_x_microns").toDouble();
            mMatroxImagingLibrary->dFOVYMicrons          = settings->value("fov_y_microns").toDouble();
            mMatroxImagingLibrary->nClockMultiplier          = settings->value("clock_multiplier").toInt();
            mMatroxImagingLibrary->nFramesPerFile          = settings->value("frames_per_file").toInt();
            mMatroxImagingLibrary->dADCMax[0]          = settings->value("adcmax_0").toDouble();
            mMatroxImagingLibrary->dADCMax[1]          = settings->value("adcmax_1").toDouble();
            mMatroxImagingLibrary->dADCMax[2]          = settings->value("adcmax_2").toDouble();
            mMatroxImagingLibrary->dADCMin[0]          = settings->value("adcmin_0").toDouble();
            mMatroxImagingLibrary->dADCMin[1]          = settings->value("adcmin_1").toDouble();
            mMatroxImagingLibrary->dADCMin[2]          = settings->value("adcmin_2").toDouble();
            mMatroxImagingLibrary->nMin[0]          = settings->value("min_0").toInt();
            mMatroxImagingLibrary->nMin[1]          = settings->value("min_1").toInt();
            mMatroxImagingLibrary->nMin[2]          = settings->value("min_2").toInt();
            mMatroxImagingLibrary->nMax[0]          = settings->value("max_0").toInt();
            mMatroxImagingLibrary->nMax[1]          = settings->value("max_1").toInt();
            mMatroxImagingLibrary->nMax[2]          = settings->value("max_2").toInt();
            mMatroxImagingLibrary->nSummationTotal          = settings->value("summation_total").toInt();
            mMatroxImagingLibrary->sFilebase          = settings->value("filebase").toString();
            mMatroxImagingLibrary->sFilename          = settings->value("filename").toString();
            mMatroxImagingLibrary->sFilepath          = settings->value("filepath").toString();

            settings->endGroup();
        }
        else
        {
            //no matrox board present
        }
    }
    else
    {
        //to make settings
        //mMatroxImagingLibrary->sFilepath


        //no existing settings. create from scratch

        printf("Creating new settings.\n");
        settings->setValue("settings", "exists");

        settings->setValue("trinamic", true);
        settings->setValue("nationalinstruments", true);
        settings->setValue("matrox", true);
        settings->setValue("resonantscanning", true);

        settings->setValue("motion_settle_ms", 1000);
        settings->setValue("slice_acquisition_time_ms", 3000);

        settings->beginGroup("Trinamic");
        settings->setValue("serial_port", L"COM1");
        settings->setValue("baudrate", 57600);
        settings->setValue("position_refresh_interval_ms",50);

        settings->setValue("x_motor", 2);
        settings->setValue("y_motor", 1);
        settings->setValue("z_motor", 0);
        settings->setValue("theta_motor", 3);

        settings->setValue("x_origin", 0.0);
        settings->setValue("y_origin", 0.0);
        settings->setValue("z_origin", 0.0);
        settings->setValue("theta_origin", 0.0);

        settings->setValue("microns_per_step_x", 0.01984375);
        settings->setValue("microns_per_step_y", 0.01984375);
        settings->setValue("microns_per_step_z", 0.078125);
        settings->setValue("radians_per_step_theta", 0.01);
        settings->setValue("trinamic_factor", 305.17578125);

        settings->setValue("rotation_mode", 0);
        settings->setValue("motorized_rotation", 0);
        settings->setValue("last_rotation_angle", 0.0);

        settings->setValue("velocity_per_bin_x", 800);
        settings->setValue("velocity_per_bin_y", 800);
        settings->setValue("velocity_per_bin_z", 200);

        settings->setValue("max_current_x", 600);
        settings->setValue("max_current_y", 600);
        settings->setValue("max_current_z", 600);
        settings->setValue("max_current_theta", 600);

        settings->setValue("full_step_threshold_x", 100);
        settings->setValue("full_step_threshold_y", 100);
        settings->setValue("full_step_threshold_z", 400);
        settings->setValue("full_step_threshold_theta", 600);

        settings->setValue("referencing_mode_x", 2);
        settings->setValue("referencing_mode_y", 2);
        settings->setValue("referencing_mode_z", 2);
        settings->setValue("referencing_mode_theta", 2);

        settings->setValue("right_limit_disable_x", 1);
        settings->setValue("right_limit_disable_y", 1);
        settings->setValue("right_limit_disable_z", 1);
        settings->setValue("right_limit_disable_theta", 1);

        settings->setValue("left_limit_disable_x", 1);
        settings->setValue("left_limit_disable_y", 1);
        settings->setValue("left_limit_disable_z", 1);
        settings->setValue("left_limit_disable_theta", 1);

        settings->setValue("max_acceleration_x", 1000);
        settings->setValue("max_acceleration_y", 1000);
        settings->setValue("max_acceleration_z", 1000);
        settings->setValue("max_acceleration_theta", 1000);

        settings->setValue("max_speed_x", 2000);
        settings->setValue("max_speed_y", 2000);
        settings->setValue("max_speed_z", 500);
        settings->setValue("max_speed_theta", 2000);

        settings->setValue("soft_stop_flag_x", 0);
        settings->setValue("soft_stop_flag_y", 0);
        settings->setValue("soft_stop_flag_z", 0);
        settings->setValue("soft_stop_flag_theta", 0);

        settings->setValue("keyboard_layout", 0);

        settings->endGroup();

        settings->beginGroup("NationalInstruments");
        settings->setValue("slowaxis_offset_volts", 0.0); //for lab, ?val
        settings->setValue("slowaxis_amplitude_volts", 8.0);
        settings->setValue("slowaxis_scanfraction", 0.3);
        settings->setValue("fastaxis_amplitude_volts", 4.0);
        settings->setValue("fastaxis_scanfraction", 1.0);
        settings->setValue("fastaxis_resonantfrequency", 8000.0);
        settings->setValue("fastaxis_pulsedelay", 291);
        settings->setValue("lines_per_frame", 512);

        settings->setValue("actuator_pinout_version", 2);
        settings->endGroup();



        settings->sync();

        SaveSettings();
        settings->sync();
    }





    //settings established, by read-in or new settings
}

void MainWindow::UpdateInterface()
{

    if(bTrinamic)
    {

        printf("Updating Trinamic UI\n");

        //rotation mode
        if(mTrinamic->bRotationMode)
        {
            ui->checkBox_rotationmode->setChecked(true);
            ui->checkBox_motorizedrotation->setDisabled(false);
            ui->doubleSpinBox_objectiveangle->setDisabled(!mTrinamic->bRotationMode);
            ui->doubleSpinBox_objectiveangle->setDisabled(mTrinamic->bMotorizedRotation);
            ui->doubleSpinBox_radius->setValue(mTrinamic->PivotRadius);
            ui->doubleSpinBox_radius->setDisabled(!mTrinamic->bMotorizedRotation);
            ui->checkBox_motorizedrotation->setChecked(mTrinamic->bMotorizedRotation);
        }
        else
        {
            ui->checkBox_rotationmode->setChecked(false);
            ui->checkBox_motorizedrotation->setDisabled(true);
            mTrinamic->bMotorizedRotation = false;
        }
        ui->motionscale_dial->setValue(mTrinamic->CurrentCoarseFineSetting);

    }
    else
    {
        //disable the trinamic box
        ui->MotionControl->setDisabled(true);
    }


    if(bNationalInstruments)
    {
        //initialize some things for scan image communication

    }
    else
    {
        ui->AcquisitionGroup->setDisabled(true);
        ui->DigitalOcular->setDisabled(true);
    }

    if(bResonantScanning)
    {
        //resonant scanning system, not scan image system
        if(!mNationalInstruments->bResonantScanning)
        {
            ui->pushButtonAcquire->setDisabled(true);
            ui->pushButtonMonitor->setDisabled(true);

        }
        else
        {
            ui->pushButtonAcquire->setDisabled(false);
            ui->pushButtonMonitor->setDisabled(false);

        }

        //Initialization first time only

        if(!bInitialized)
        {

            //Set lines per frame by search
            QString temp;
            temp.sprintf("%d",mNationalInstruments->nLinesPerFrame);
            ui->comboBox_linesperframe->setCurrentIndex(
               ui->comboBox_linesperframe->findText(temp)
                        );

            //default MAGNIFICATION 1
            //we can change magnification and update scan fractions safely
            //without starting resonant scanning
            printf("Setting Magnificiation\n");
            ui->comboBox_magnification->setCurrentIndex(0);
            printf("Finished setting Magnificiation\n");
            //will update ui, and mNationalInstruments scan fraction values
            SetMagnification(1);

            ui->spinBox_pulsedelay->setValue(mNationalInstruments->nPulseDelay1x);
            //transfer
        }

        //Update scanning box items
        {
            printf("Updating NI UI\n");
            //initialize some ui
            //transfer to "National Instruments update ui" function
            ui->doubleSpinBox_framerate->setValue(
                        mNationalInstruments->dXResonanceFrequency/(mNationalInstruments->nLinesPerFrame/2
                                            ));

            //ui->doubleSpinBox_fastzoom->setValue(mNationalInstruments->dXScanFraction);
            //ui->doubleSpinBox_slowzoom->setValue(mNationalInstruments->dYScanFraction);
            ui->checkBox_fastblank->setChecked(mNationalInstruments->bFastBlank);
            ui->checkBox_slowblank->setChecked(mNationalInstruments->bSlowBlank);
            ui->doubleSpinBox_laserpower->setValue(mNationalInstruments->dLaserPower);
            ui->doubleSpinBox_flyback->setValue(1.0-mNationalInstruments->dYRampDutyCycle);
            ui->doubleSpinBox_fastfreq->setValue(mNationalInstruments->dFastFreq);

            ui->doubleSpinBox_fastwidth->setValue(mNationalInstruments->dFastBlankWidth);
            ui->doubleSpinBox_fastdelay->setValue(mNationalInstruments->dFastBlankDelay);
            ui->doubleSpinBox_slowwidth->setValue(mNationalInstruments->dSlowBlankWidth);
            ui->doubleSpinBox_slowdelay->setValue(mNationalInstruments->dSlowBlankDelay);


        }

    }
    else
    {
        //This is a standard scanning system, disable scanning panels
        ui->AcquisitionGroup->setDisabled(true);
        //ui->ScanningGroup->setDisabled(true);

        //If this is a translation only system, open external stack panel
        //ui->tab_stackexp->setWindowState(Qt::WindowActive);
    }

    if(bMatrox)
    {

        printf("Updating Matrox UI\n");
        //settings->beginGroup("Matrox");
        //ui->AcquisitionGroup->setDisabled(true);


        //update main box items
        {

            ui->checkBox_fragment->setChecked(mMatroxImagingLibrary->bFragment);
            ui->spinBox_fragmentsize->setValue(mMatroxImagingLibrary->nFragmentSize);
            ui->spinBox_AcqNumber->setValue(mMatroxImagingLibrary->nAcquisitionNumber);
            ui->spinBox_frames->setValue(mMatroxImagingLibrary->nFramesPerFile );
            ui->checkBox_exttrigger->setChecked(mMatroxImagingLibrary->bExtTrigger);
            ui->checkBox_retriggerable->setChecked(mMatroxImagingLibrary->bRetrigger);

            ui->checkBox_fastprocess->setChecked(mMatroxImagingLibrary->bBareTransform);

            UpdateFilenameToUi();
        }

        //update channel box items
        {
            ui->doubleSpinBox_gain1->setValue(mMatroxImagingLibrary->dADCMax[0]);
            ui->doubleSpinBox_gain2->setValue(mMatroxImagingLibrary->dADCMax[1]);
            ui->doubleSpinBox_gain3->setValue(mMatroxImagingLibrary->dADCMax[2]);
            ui->doubleSpinBox_gain1_2->setValue(mMatroxImagingLibrary->dADCMin[0]);
            ui->doubleSpinBox_gain2_2->setValue(mMatroxImagingLibrary->dADCMin[1]);
            ui->doubleSpinBox_gain3_2->setValue(mMatroxImagingLibrary->dADCMin[2]);
            ui->spinBox_max_1->setValue(mMatroxImagingLibrary->nMax[0]);
            ui->spinBox_max_2->setValue(mMatroxImagingLibrary->nMax[1]);
            ui->spinBox_max_3->setValue(mMatroxImagingLibrary->nMax[2]);
            ui->spinBox_min_1->setValue(mMatroxImagingLibrary->nMin[0]);
            ui->spinBox_min_2->setValue(mMatroxImagingLibrary->nMin[1]);
            ui->spinBox_min_3->setValue(mMatroxImagingLibrary->nMin[2]);

            ui->checkBox_save1->setChecked(mMatroxImagingLibrary->bSaveChannel[0]);
            ui->checkBox_save2->setChecked(mMatroxImagingLibrary->bSaveChannel[1]);
            ui->checkBox_save3->setChecked(mMatroxImagingLibrary->bSaveChannel[2]);
        }

        //update post-processing items
        {
            ui->checkBoxAC->setChecked(mMatroxImagingLibrary->bACCoupling);
            //ui->->setChecked(mMatroxImagingLibrary->bFlipRes);
            ui->checkBox_slowbd->setChecked(mMatroxImagingLibrary->bFlipSlow);
            ui->checkBox_flipx->setChecked(mMatroxImagingLibrary->bFlipX);
            ui->checkBox_flipy->setChecked(mMatroxImagingLibrary->bFlipY);
            ui->checkBoxInvert->setChecked(mMatroxImagingLibrary->bInvert);
            ui->checkBoxLog->setChecked(mMatroxImagingLibrary->bLog);
            ui->checkBoxMean->setChecked(mMatroxImagingLibrary->bMeanConvolve);
            ui->checkBoxMedian->setChecked(mMatroxImagingLibrary->bMedianConvolve);
            ui->spinBox_sumframes->setValue(mMatroxImagingLibrary->nSummationTotal);
            ui->checkBoxSine->setChecked(mMatroxImagingLibrary->bWarp);
        }

        //update compute items
        {
            //ui->checkBox_computegbratio->setChecked(mMatroxImagingLibrary->bCompGBRatio);
            ui->checkBox_computehistograms->setChecked(mMatroxImagingLibrary->bCompHistograms);
            ui->checkBox_computeroitraces->setChecked(mMatroxImagingLibrary->bCompTraces);
        }

        //update overlay items
        {
            ui->checkBox_showcrosshairs->setChecked(mMatroxImagingLibrary->bOvCrosshairs);
            ui->checkBox_showoverlay->setChecked(mMatroxImagingLibrary->bOverlay);
            ui->checkBox_showexposure->setChecked(mMatroxImagingLibrary->bOvExposure);
            ui->checkBox_showframenumber->setChecked(mMatroxImagingLibrary->bOvFramenumber);
            ui->checkBox_showrois->setChecked(mMatroxImagingLibrary->bOvLiveGrid);
            ui->checkBox_showoverlayimage->setChecked(mMatroxImagingLibrary->bOvOverlayImage);
            ui->checkBox_showposition->setChecked(mMatroxImagingLibrary->bOvPosition);
            //ui->check->setChecked(mMatroxImagingLibrary->bOvScalebars);
        }



        //ui->AcquisitionGroup->setDisabled(false);

        //update disabled/enabled state
        //STATE MACHINE monitoring/acquiring
        if(mMatroxImagingLibrary->bMonitoring)
        {
            ui->pushButtonMonitor->setText("Stop Monitor");
            ui->pushButtonAcquire->setDisabled(true);
            ui->pushButtonMonitor->setDisabled(false);

            ui->widget_basicacquisition->setDisabled(true);

            ui->comboBox_linesperframe->setDisabled(true);
            ui->reset_display->setDisabled(true);
            ui->spinBox_frames->setDisabled(true);
            ui->pushButton_savedisplaytooverlay->setDisabled(true);

            ui->pushButton_acquirezstack->setDisabled(0);
            ui->pushButton_acquirezstack->setDisabled(0);
            ui->pushButton_acquirezstack->setDisabled(0);
            ui->pushButton_acquirezstack->setDisabled(0);
        }
        else if(mMatroxImagingLibrary->bAcquiring)
        {
            ui->pushButtonAcquire->setText("Stop Acquisition");
            ui->pushButtonMonitor->setDisabled(true);
            ui->pushButtonAcquire->setDisabled(false);

            ui->widget_basicacquisition->setDisabled(true);

            ui->comboBox_linesperframe->setDisabled(true);
            ui->reset_display->setDisabled(true);
            ui->spinBox_frames->setDisabled(true);
            ui->pushButton_savedisplaytooverlay->setDisabled(true);
        }
        else if(!mMatroxImagingLibrary->bMonitoring && !mMatroxImagingLibrary->bAcquiring)
        {
            ui->pushButtonMonitor->setText("Monitor");
            ui->pushButtonAcquire->setText("Acquire");

            ui->widget_basicacquisition->setDisabled(false);
            ui->pushButtonMonitor->setDisabled(false);
            ui->pushButtonAcquire->setDisabled(false);

            ui->comboBox_linesperframe->setDisabled(false);
            ui->reset_display->setDisabled(false);
            ui->spinBox_frames->setDisabled(false);
            ui->pushButton_savedisplaytooverlay->setDisabled(false);

        }

        //STATE MACHINE
        if(!mNationalInstruments->bResonantScanning)
        {

            ui->pushButtonMonitor->setDisabled(true);
            ui->pushButtonAcquire->setDisabled(true);
        }

        //STATE MACHINE
        if(!ui->checkBox_exttrigger)
        {
            ui->checkBox_retriggerable->setDisabled(true);
        }
        else
        {
            ui->checkBox_retriggerable->setDisabled(false);
        }

        //STATE MACHINE
        if(this->bAcquiringStack)
        {

        }
        else if(this->bAcquiringStack_Fast)
        {
            ui->pushButton_fastzstack->setText("Stop Fast Stack");
            ui->tab_mosaic->setDisabled(1);
        }
        else if(this->bAcquiringStack_Precise)
        {
            ui->pushButton_precisezstack->setText("Stop Stack");
            ui->tab_mosaic->setDisabled(1);
        }
        else if(this->bAcquiringMosaic)
        {
            ui->pushButton_mosaic2d->setText("Stop Mosaic");
            ui->tab_stack->setDisabled(1);
        }
        else
        {

            //not acquiring any stacks

            if(bStackPreciseReady)
            {
                ui->pushButton_precisezstack->setDisabled(0);
                ui->pushButton_fastzstack->setDisabled(0);
                ui->pushButton_mosaic3d->setDisabled(0);
                ui->pushButton_mosaic3d_fast->setDisabled(0);
                ui->pushButton_precisezstack->setText("Start Precise Stack");
                ui->pushButton_fastzstack->setText("Start Fast Stack");
                ui->pushButton_mosaic2d->setText("2D Mosaic");
            }
            else
            {
                ui->pushButton_precisezstack->setDisabled(1);
                ui->pushButton_fastzstack->setDisabled(1);
                ui->pushButton_mosaic3d->setDisabled(1);
                ui->pushButton_mosaic3d_fast->setDisabled(1);
                //ui->pushButton_precisezstack->setText("Start Precise Stack");
            }

            ui->AcquisitionGroup->setDisabled(false);
            ui->tab_mosaic->setDisabled(0);
            ui->tab_stack->setDisabled(0);
        }
    }
    else
    {

        //Also in standard scanning mode?

        ui->AcquisitionGroup->setDisabled(true);
        //no matrox board present
        ui->pushButtonAcquire->setDisabled(true);
        ui->pushButtonMonitor->setDisabled(true);
        //ui->DisplayandprocessingGroup->setDisabled(true);
    }

}

void MainWindow::TimerTasks()
{

    //This function acts as an internal event queue

    //Stop tasks are processed first, to allow stop and start to be
    //queued in the right order.

    if(bTaskStopMonitor)
    {
        printf("Asynchronous stop monitor requested...\n");
        StopMonitor();
        bTaskStopMonitor = false;
    }
    if(bTaskStopAcquire)
    {
        printf("Asynchronous stop acquire requested...\n");
        StopAcquire();
        bTaskStopAcquire = false;
    }
    if(bTaskUpdateUi)
    {
        printf("Asynchronous update ui requested...\n");
        UpdateInterface();
        bTaskUpdateUi = false;
    }

    //these placed after stop tasks, for proper retrigger function
    if(bTaskStartMonitor)
    {
        printf("Asynchronous start monitor requested...\n");
        StartMonitor();
        bTaskStartMonitor = false;
    }
    if(bTaskStartAcquire)
    {
        printf("Asynchronous start acquire requested...\n");
        StartAcquire();
        bTaskStartAcquire = false;
    }

    //check current stack start distance

    if(!this->bAcquiringStack_Precise )
    {
        if(abs(this->dPreciseStackStart - mTrinamic->CurrentPositionRotated[mTrinamic->ZMotor]) > 1000.0)
        {
            ui->pushButton_precisezstack->setText("Warning: > 1mm from start");
            ui->pushButton_mosaic3d_fast->setText("Warning: > 1mm from start");
            ui->pushButton_mosaic3d->setText("Warning: > 1mm from start");
            bStackPreciseReady = false;
        }
        else
        {
            ui->pushButton_precisezstack->setText("Precise Stack");
            ui->pushButton_mosaic3d_fast->setText("Fast Stack Mosaic");
            ui->pushButton_mosaic3d->setText("Stack Mosaic");
            bStackPreciseReady = true;
        }
    }


    //occasionally check for script file
    ReadScriptFile();

    //reset rectraction counter
    if(nResetCount > 3)
    {
        nRetractCount = 0;
        nResetCount = 0;
    }
    else
    {
        nResetCount++;
    }

    mMatroxImagingLibrary->nTriggerCount++;


    return;
}

void MainWindow::SaveSettings()
{


    settings->beginGroup("NationalInstruments");

    settings->setValue("fastfreq", mNationalInstruments->dFastFreq);

    settings->setValue("fastwidth", mNationalInstruments->dFastBlankWidth);
    settings->setValue("fastdelay", mNationalInstruments->dFastBlankDelay);
    settings->setValue("slowwidth", mNationalInstruments->dSlowBlankWidth);
    settings->setValue("slowdelay", mNationalInstruments->dSlowBlankDelay);


    settings->setValue("hblank_duration", mNationalInstruments->nEdgeWidth);
    settings->setValue("slowaxis_offset_volts", mNationalInstruments->dYScanOffsetVolts); //for lab, ?val
    settings->setValue("slowaxis_amplitude_volts", mNationalInstruments->dYScanAmplitudeVolts);
    settings->setValue("slowaxis_scanfraction", mNationalInstruments->dYScanFraction);
    settings->setValue("fastaxis_amplitude_volts", mNationalInstruments->dXScanAmplitudeVolts);
    settings->setValue("fastaxis_scanfraction", mNationalInstruments->dXScanFraction);
    settings->setValue("fastaxis_resonantfrequency", mNationalInstruments->dXResonanceFrequency);
    settings->setValue("fastaxis_pulsedelay", mNationalInstruments->nPulseDelay);
    settings->setValue("fastaxis_pulsedelay_1x", mNationalInstruments->nPulseDelay1x);
    settings->setValue("fastaxis_pulsedelay_2x", mNationalInstruments->nPulseDelay2x);
    settings->setValue("fastaxis_pulsedelay_4x", mNationalInstruments->nPulseDelay4x);
    settings->setValue("fastaxis_pulsedelay_8x", mNationalInstruments->nPulseDelay8x);
    settings->setValue("fastaxis_pulsedelay_16x", mNationalInstruments->nPulseDelay16x);
    settings->setValue("fastaxis_pulsedelay_32x", mNationalInstruments->nPulseDelay32x);
    settings->setValue("fastaxis_pulsedelay_64x", mNationalInstruments->nPulseDelay64x);
    settings->setValue("fastaxis_fastfreq_1x", mNationalInstruments->dFastFreq1x);
    settings->setValue("fastaxis_fastfreq_2x", mNationalInstruments->dFastFreq2x);
    settings->setValue("fastaxis_fastfreq_4x", mNationalInstruments->dFastFreq4x);
    settings->setValue("fastaxis_fastfreq_8x", mNationalInstruments->dFastFreq8x);
    settings->setValue("fastaxis_fastfreq_16x", mNationalInstruments->dFastFreq16x);
    settings->setValue("fastaxis_fastfreq_32x", mNationalInstruments->dFastFreq32x);
    settings->setValue("fastaxis_fastblankdelay_1x", mNationalInstruments->dFastBlankDelay1x);
    settings->setValue("fastaxis_fastblankdelay_2x", mNationalInstruments->dFastBlankDelay2x);
    settings->setValue("fastaxis_fastblankdelay_4x", mNationalInstruments->dFastBlankDelay4x);
    settings->setValue("fastaxis_fastblankdelay_8x", mNationalInstruments->dFastBlankDelay8x);
    settings->setValue("fastaxis_fastblankdelay_16x", mNationalInstruments->dFastBlankDelay16x);
    settings->setValue("fastaxis_fastblankdelay_32x", mNationalInstruments->dFastBlankDelay32x);



    settings->setValue("fastblank", mNationalInstruments->bFastBlank);
    settings->setValue("slowblank", mNationalInstruments->bSlowBlank);
    settings->setValue("laserpower", mNationalInstruments->dLaserPower);
    settings->setValue("actuator_pinout_version", mNationalInstruments->nActuatorPinoutVersion);
    settings->setValue("lines_per_frame", mNationalInstruments->nLinesPerFrame);
    settings->setValue("slowaxis_flybackfraction", 1.0 - mNationalInstruments->dYRampDutyCycle);

    settings->endGroup();

    settings->beginGroup("Trinamic");

    //settings->setValue("", mTrinamic->cu);
    settings->setValue("coarse_fine_setting", mTrinamic->CurrentCoarseFineSetting);
    settings->setValue("rotation_mode", mTrinamic->bRotationMode);
    settings->setValue("motorized_rotation", mTrinamic->bMotorizedRotation);
    settings->setValue("pivot_radius",mTrinamic->PivotRadius);
    settings->setValue("x_origin",mTrinamic->RelativeModeOrigin[mTrinamic->XMotor]);
    settings->setValue("y_origin",mTrinamic->RelativeModeOrigin[mTrinamic->YMotor]);
    settings->setValue("z_origin",mTrinamic->RelativeModeOrigin[mTrinamic->ZMotor]);
    settings->setValue("theta_origin",mTrinamic->RelativeModeOrigin[mTrinamic->ThetaMotor]);
    settings->setValue("polarity_x",mTrinamic->Polarity[mTrinamic->XMotor]);
    settings->setValue("polarity_y",mTrinamic->Polarity[mTrinamic->YMotor]);
    settings->setValue("polarity_z",mTrinamic->Polarity[mTrinamic->ZMotor]);
    settings->setValue("polarity_theta",mTrinamic->Polarity[mTrinamic->ThetaMotor]);
    /*
    settings->setValue("", mTrinamic->);
    settings->setValue("", mTrinamic);
    settings->setValue("", mTrinamic);
    settings->setValue("", mTrinamic);
    settings->setValue("", mTrinamic);
    settings->setValue("", mTrinamic);
    settings->setValue("", mTrinamic);
    settings->setValue("", mTrinamic);
    settings->setValue("", mTrinamic);
    */
    settings->endGroup();

    settings->beginGroup("Matrox");

    settings->setValue("adc_mhz", mMatroxImagingLibrary->mhz);
    settings->setValue("save_channel_1", mMatroxImagingLibrary->bSaveChannel[0]);
    settings->setValue("save_channel_2", mMatroxImagingLibrary->bSaveChannel[1]);
    settings->setValue("save_channel_3", mMatroxImagingLibrary->bSaveChannel[2]);
    settings->setValue("fragment_size", mMatroxImagingLibrary->nFragmentSize);
    settings->setValue("fragment", mMatroxImagingLibrary->bFragment);
    settings->setValue("ac_coupling", mMatroxImagingLibrary->bACCoupling);
    settings->setValue("compute_bluegreen_ratio", mMatroxImagingLibrary->bCompGBRatio);
    settings->setValue("compute_histograms", mMatroxImagingLibrary->bCompHistograms);
    settings->setValue("compute_traces", mMatroxImagingLibrary->bCompTraces);
    settings->setValue("external_trigger", mMatroxImagingLibrary->bExtTrigger);
    settings->setValue("flip_res", mMatroxImagingLibrary->bFlipRes);
    settings->setValue("flip_slow", mMatroxImagingLibrary->bFlipSlow);
    settings->setValue("flip_x", mMatroxImagingLibrary->bFlipX);
    settings->setValue("flip_y", mMatroxImagingLibrary->bFlipY);
    settings->setValue("invert", mMatroxImagingLibrary->bInvert);
    settings->setValue("log", mMatroxImagingLibrary->bLog);
    settings->setValue("mean", mMatroxImagingLibrary->bMeanConvolve);
    settings->setValue("median", mMatroxImagingLibrary->bMedianConvolve);
    settings->setValue("overlay_crosshairs", mMatroxImagingLibrary->bOvCrosshairs);
    settings->setValue("overlay", mMatroxImagingLibrary->bOverlay);
    settings->setValue("overlay_exposure", mMatroxImagingLibrary->bOvExposure);
    settings->setValue("overlay_framenumber", mMatroxImagingLibrary->bOvFramenumber);
    settings->setValue("overlay_livegrid", mMatroxImagingLibrary->bOvLiveGrid);
    settings->setValue("overlay_image", mMatroxImagingLibrary->bOvOverlayImage);
    settings->setValue("overlay_position", mMatroxImagingLibrary->bOvPosition);
    settings->setValue("overlay_scalebars", mMatroxImagingLibrary->bOvScalebars);
    settings->setValue("retrigger", mMatroxImagingLibrary->bRetrigger);
    settings->setValue("sine_warp", mMatroxImagingLibrary->bWarp);
    settings->setValue("fov_x_microns", mMatroxImagingLibrary->dFOVXMicrons);
    settings->setValue("fov_y_microns", mMatroxImagingLibrary->dFOVYMicrons);
    settings->setValue("clock_multiplier", mMatroxImagingLibrary->nClockMultiplier);
    settings->setValue("frames_per_file", mMatroxImagingLibrary->nFramesPerFile);
    settings->setValue("adcmax_0", mMatroxImagingLibrary->dADCMax[0]);
    settings->setValue("adcmax_1", mMatroxImagingLibrary->dADCMax[1]);
    settings->setValue("adcmax_2", mMatroxImagingLibrary->dADCMax[2]);
    settings->setValue("adcmin_0", mMatroxImagingLibrary->dADCMin[0]);
    settings->setValue("adcmin_1", mMatroxImagingLibrary->dADCMin[1]);
    settings->setValue("adcmin_2", mMatroxImagingLibrary->dADCMin[2]);
    settings->setValue("min_0", mMatroxImagingLibrary->nMin[0]);
    settings->setValue("min_1", mMatroxImagingLibrary->nMin[1]);
    settings->setValue("min_2", mMatroxImagingLibrary->nMin[2]);
    settings->setValue("max_0", mMatroxImagingLibrary->nMax[0]);
    settings->setValue("max_1", mMatroxImagingLibrary->nMax[1]);
    settings->setValue("max_2", mMatroxImagingLibrary->nMax[2]);
    settings->setValue("summation_total", mMatroxImagingLibrary->nSummationTotal);
    settings->setValue("filebase", mMatroxImagingLibrary->sFilebase);
    settings->setValue("filename", mMatroxImagingLibrary->sFilename);
    settings->setValue("filepath", mMatroxImagingLibrary->sFilepath);
    settings->endGroup();


    //settings->beginGroup("Main");
    //settings->endGroup();

    settings->sync();

    printf("Saved settings.\n");

}


void MainWindow::OutputReport(bool bSavemonitor)
{

    QString temp;

    //Parse the DCF file
    temp = mMatroxImagingLibrary->sFilepath +
            mMatroxImagingLibrary->sFilebase +
            "/" +
            mMatroxImagingLibrary->sFilebase +
            temp.sprintf("%03d",
                         (mMatroxImagingLibrary->nAcquisitionNumber-1))
             +
            ".txt";
    QFile qReport(temp);
    printf("Recording acquisition parameters to %s\n", temp.toLocal8Bit().data());

    if( !qReport.open(QIODevice::ReadWrite | QIODevice::Text) )
    {
        QDebug(QtDebugMsg) << "Failed to write acquisition parameters \n";
    }

    QTextStream out(&qReport);
    out.reset();

    //Scanning parameters
    out << "Lines per frame " << mNationalInstruments->nLinesPerFrame << endl;
    out << "Resonant freq " << mNationalInstruments->dXResonanceFrequency << endl;
    out << "Fast scan volts " << mNationalInstruments->dXScanAmplitudeVolts << endl;
    out << "Fast scan fraction " << mNationalInstruments->dXScanFraction << endl;
    out << "Slow scan duty cycle " << mNationalInstruments->dYRampDutyCycle << endl;
    out << "Slow scan volts " << mNationalInstruments->dYScanAmplitudeVolts << endl;
    out << "Slow scan fraction " << mNationalInstruments->dYScanFraction << endl;
    out << "Slow scan offset volts " << mNationalInstruments->dYScanOffsetVolts << endl;
    out << "Fast scan delay " << mNationalInstruments->nPulseDelay << endl;
    out << "Fast scan blank " << mNationalInstruments->bFastBlank << endl;
    out << "Slow scan blank " << mNationalInstruments->bSlowBlank << endl;

    //ADC parameters
    out << "Ch1(R) saved " << mMatroxImagingLibrary->bSaveChannel[0] << endl;
    out << "Ch2(G) saved " << mMatroxImagingLibrary->bSaveChannel[1] << endl;
    out << "Ch3(B) saved " << mMatroxImagingLibrary->bSaveChannel[2] << endl;
    out << "Ch4(X) saved " << mMatroxImagingLibrary->bSaveChannel[3] << endl;

    out << "Ch1(R) adcmax " << mMatroxImagingLibrary->dADCMax[0] << endl;
    out << "Ch2(G) adcmax " << mMatroxImagingLibrary->dADCMax[1] << endl;
    out << "Ch3(B) adcmax " << mMatroxImagingLibrary->dADCMax[2] << endl;
    out << "Ch4(X) adcmax " << mMatroxImagingLibrary->dADCMax[3] << endl;
    out << "Ch1(R) adcmin " << mMatroxImagingLibrary->dADCMin[0] << endl;
    out << "Ch2(G) adcmin " << mMatroxImagingLibrary->dADCMin[1] << endl;
    out << "Ch3(B) adcmin " << mMatroxImagingLibrary->dADCMin[2] << endl;
    out << "Ch4(X) adcmin " << mMatroxImagingLibrary->dADCMin[3] << endl;
    //out << "Horizontal back porch " << mMatroxImagingLibrary->nBackPorch << endl;
    out << "ADC clock " << mMatroxImagingLibrary->mhz << endl;
    //out << "ADC clock multiplier " << mMatroxImagingLibrary->nClockMultiplier << endl;


    out << "External trigger " << mMatroxImagingLibrary->bExtTrigger << endl;
    out << "External retrigger " << mMatroxImagingLibrary->bRetrigger << endl;
    out << "Resonant BD flip " << mMatroxImagingLibrary->bFlipRes << endl;
    out << "Slow scan BD flip " << mMatroxImagingLibrary->bFlipSlow << endl;
    out << "Fast axis flip " << mMatroxImagingLibrary->bFlipX << endl;
    out << "Slow axis flip " << mMatroxImagingLibrary->bFlipY << endl;
    out << "LUT invert " << mMatroxImagingLibrary->bInvert << endl;
    out << "Log display " << mMatroxImagingLibrary->bLog << endl;
    out << "Mean convolve display " << mMatroxImagingLibrary->bMeanConvolve << endl;
    out << "Median filter display " << mMatroxImagingLibrary->bMedianConvolve << endl;
    out << "Sine correction display " << mMatroxImagingLibrary->bWarp << endl;
    out << "Acquire raw data " << !bSavemonitor << endl;
    out << "Acquire (save) monitor " << bSavemonitor << endl;
    out << "Theoretical framerate " << mMatroxImagingLibrary->dFramerate << endl;
    out << "Summation, ie temporal binning " << mMatroxImagingLibrary->nSummationTotal << endl;
    out << "Archived frames " << mMatroxImagingLibrary->UserHookData.nArchivedFrames << endl;
    out << "Framegrabber frames missed " << mMatroxImagingLibrary->nMissed << endl;
    out << "Framegrabber frames grabbed, including extra " << mMatroxImagingLibrary->ProcessFrameCount << endl;
    out << "Effective framerate " << mMatroxImagingLibrary->ProcessFrameRate << endl;
    out << "Acquisition number " << mMatroxImagingLibrary->nAcquisitionNumber << endl;
    out << "Fragment size " << mMatroxImagingLibrary->nFragmentSize << endl;
    out << "Frames per file " << mMatroxImagingLibrary->nFramesPerFile << endl;
    out << "Total files " << mMatroxImagingLibrary->UserHookData.nTotalFiles << endl;
    out << "Raw X size " << mMatroxImagingLibrary->UserHookData.nSizeX << endl;
    out << "Raw Y size " << mMatroxImagingLibrary->UserHookData.nSizeY << endl;

    //Positioning
    out << "Position microns X " << mTrinamic->CurrentPositionMicrons[mTrinamic->XMotor] << endl;
    out << "Position microns Y " << mTrinamic->CurrentPositionMicrons[mTrinamic->YMotor] << endl;
    out << "Position microns Z " << mTrinamic->CurrentPositionMicrons[mTrinamic->ZMotor] << endl;
    out << "Position steps X " << mTrinamic->CurrentPositionSteps[mTrinamic->XMotor] << endl;
    out << "Position steps Y " << mTrinamic->CurrentPositionSteps[mTrinamic->YMotor] << endl;
    out << "Position steps Z " << mTrinamic->CurrentPositionSteps[mTrinamic->ZMotor] << endl;
    out << "Position microns rotated X " << mTrinamic->CurrentPositionRotated[mTrinamic->XMotor] << endl;
    out << "Position microns rotated Y " << mTrinamic->CurrentPositionRotated[mTrinamic->YMotor] << endl;
    out << "Position microns rotated Z " << mTrinamic->CurrentPositionRotated[mTrinamic->ZMotor] << endl;
    out << "XZ Rotation angle " << mTrinamic->XZRotationAngle << endl;


    qReport.close();

    printf("Saved report.\n");
    return;
}


void MainWindow::ReadScriptFile()
{

    QString script_name = "multiphoton_script.txt";
    QString script_name_finished = "multiphoton_script_parsed.txt";
    QString temp1;
    temp1 = script_name;


    QFile qScript(temp1);

    if(!qScript.exists())
    {
        return;
    }
    else
    {
        printf("Reading detected script file from %s\n", temp1.toLocal8Bit().data());

        if( !qScript.open(QIODevice::ReadWrite | QIODevice::Text) )
        {
            QDebug(QtDebugMsg) << "Failed to read script \n";
        }


        QTextStream in(&qScript);
        in.reset();

        int ncommands = 0;

        //Take the text file, and read in all the lines. Enter them verbatim as script.
        while(!in.atEnd())
        {
            QString temp;
            temp = in.readLine();
            CurrentScript.push_back(temp);
            ncommands++;
        }

        //Start the script
        if(ncommands > 0)
        {

            bWaitingForLastFinish = false;

            printf("Starting External Script\n");
            for(int i = 0; i < CurrentScript.size(); i++)
            {
                printf("%s\n",CurrentScript[i].toLocal8Bit().data());
            }

            //script will run until empty, and stop its timer
            bRunningScript = true;
            mTimerScript.start(300);
        }

        qScript.close();
        qScript.remove(script_name_finished);
        qScript.rename(script_name, script_name_finished);


        printf("Read in Script-API file.\n");

        return;
    }
}

void MainWindow::UpdateFilename()
{
    printf("Updating Filename from input boxes.\n");
    mMatroxImagingLibrary->sFilebase = ui->lineEdit_dataset->text();
    mMatroxImagingLibrary->sFilepath = ui->lineEdit_pathname->text();
    mMatroxImagingLibrary->UpdateFilename();
    printf("Filename: %s\n", mMatroxImagingLibrary->sFilename.toAscii().data());
    ui->lineEdit_filename->setPlainText(mMatroxImagingLibrary->sFilename);
    ui->lineEdit_filename->update();

    //ui->lineEdit_filename->setText("lksdf");
    return;

}

void MainWindow::UpdateFilenameToUi()
{
    printf("Updating filename input boxes\n");
    ui->lineEdit_dataset->setText(mMatroxImagingLibrary->sFilebase);
    ui->lineEdit_pathname->setText(mMatroxImagingLibrary->sFilepath);
    ui->spinBox_AcqNumber->setValue(mMatroxImagingLibrary->nAcquisitionNumber);

    //due to message about QT objects, child, different thread
    QString temp = mMatroxImagingLibrary->sFilename;
    ui->lineEdit_filename->setPlainText(temp);
    ui->lineEdit_filename->update();
    printf("Filename: %s\n", mMatroxImagingLibrary->sFilename.toAscii().data());
}

HANDLE MainWindow::OpenSerial(LPCWSTR ComName, DWORD Baudrate)
{
    //_T("mystring");
    //reinterpret_cast<const wchar_t *>(QString("COM1").utf16()

    //set variable
    HANDLE hSerial;
    hSerial = (HANDLE)-1;

    //try to open com port
    hSerial = CreateFile(ComName,
    GENERIC_READ | GENERIC_WRITE,
    0,
    0,
    OPEN_EXISTING,
    //                      0,
    FILE_ATTRIBUTE_NORMAL,
    0);

    if(hSerial==INVALID_HANDLE_VALUE)
    {
        if(GetLastError()==ERROR_FILE_NOT_FOUND){
        //serial port does not exist. Inform user.
            printf("RS232: Serial port not found.  Verify com port and restart program.\n");
            return hSerial;
        }
        //some other error occurred. Inform user.
       printf("RS232: Unknown error occurred.  Please restart program.\n");
        return hSerial;
    }

    //try to set parameters

    printf("Trinamic - Opening com port 1, baudrate %d.\n", Baudrate);

    DCB dcbSerialParams = {0};
    dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
    if (!GetCommState(hSerial, &dcbSerialParams)) {
        printf("RS232: Error getting state.  Verify com port and restart program.\n");
    //error getting state
    }
    dcbSerialParams.BaudRate=Baudrate;//Baudrate;//Baudrate;
    dcbSerialParams.ByteSize=8;
    dcbSerialParams.StopBits=ONESTOPBIT;
    dcbSerialParams.Parity=NOPARITY;

    dcbSerialParams.fBinary=1;  //Binary Mode only
    dcbSerialParams.fParity=0;
    dcbSerialParams.fOutxCtsFlow=0;
    dcbSerialParams.fOutxDsrFlow=0;
    dcbSerialParams.fDtrControl=0;
    dcbSerialParams.fDsrSensitivity=0;
    dcbSerialParams.fTXContinueOnXoff=0;
    dcbSerialParams.fOutX=0;
    dcbSerialParams.fInX=0;
    dcbSerialParams.fErrorChar=0;
    dcbSerialParams.fNull=0;
    dcbSerialParams.fRtsControl=RTS_CONTROL_TOGGLE;
    dcbSerialParams.fAbortOnError=0;

    if(!SetCommState(hSerial, &dcbSerialParams))
    {

        printf("RS232: Error setting state. Verify com port and restart program\n");
        return hSerial;
    }

    //SetupComm(hSerial, 100, 100);

    COMMTIMEOUTS CommTimeouts;
    GetCommTimeouts(hSerial, &CommTimeouts);

    CommTimeouts.ReadIntervalTimeout=MAXDWORD;
    CommTimeouts.ReadTotalTimeoutMultiplier=0;
    CommTimeouts.ReadTotalTimeoutConstant=0;

    SetCommTimeouts(hSerial, &CommTimeouts);

//    //Attempt Set timeouts for the port
//    COMMTIMEOUTS timeouts={0};
//    timeouts.ReadIntervalTimeout=3;
//    timeouts.ReadTotalTimeoutConstant=2;
//    timeouts.ReadTotalTimeoutMultiplier=3;
//    timeouts.WriteTotalTimeoutConstant=2;
//    timeouts.WriteTotalTimeoutMultiplier=3;

//    if(!SetCommTimeouts(hSerial, &timeouts))
//    {
//        printf("RS232: Couldn't set timeouts.  Check the comm cable settings");
//        return hSerial;
//    }

    //if no other errors occured, port is open
    QDebug(QtDebugMsg) << "RS232: Communication port open." << endl;


    bCommPortOpen = true;

    return hSerial;
}

void MainWindow::CloseSerial(HANDLE hSerial)
{

//    int n = 10;
//    wchar_t szBuff[10 + 1] = {0};
//    DWORD dwBytesRead = 0;
//    if(!ReadFile(hSerial, szBuff, n, &dwBytesRead, NULL)){

//    }
//    //error occurred. Report to user.


    CloseHandle(hSerial);

    wchar_t lastError[1024];
    FormatMessage(
    FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
    NULL,
    GetLastError(),
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    lastError,
    1024,
    NULL);

    bCommPortOpen = false;

    return;
}


//TODO: setup NIDAQmx class and pre-arm tasks


void MainWindow::TriggerScanImage()
{

    mNationalInstruments->OutputDigitalPulse("Dev1/Port1/Line1",1);

}


void MainWindow::MoveFirgelli(int setposition, int id)
{

    mNationalInstruments->ChangeFirgelliState(setposition, id);

    return;
}

void MainWindow::AcquireZStack(double ZPitchMicrons, int nFrames)
{

    //double current_z_position_microns = mTrinamic->CurrentPositionMicrons[mTrinamic->ZMotor];

    nZStackCurrentSlice = 0;
    nZStackTotalSlices = nFrames;
    dZStackPitch = ZPitchMicrons;

    if(bResonantScanning)
    {
        UpdateMatrox();
        UpdateFilename();

        if(!mMatroxImagingLibrary->bMonitoring)
        {
            StartMonitor();
            ui->pushButtonMonitor->setText("Stop Monitor-Stack");
        }
    }

    //Starts timer with 3 second hardcoded delay, and waits for callback
    mTimerStack.start(nAcquisitionTimeMilliseconds);
    bAcquiringStack = true;
    printf("Starting stack.\n");
}

void MainWindow::StopZStack()
{
    //Now refers to external stack
    if(bAcquiringStack)
    {
        //finished stack
        mTimerStack.stop();
        //display some message here
        if(bResonantScanning)
        {
            if(mMatroxImagingLibrary->bMonitoring)
            {
                StopMonitor();
            }
        }
        bAcquiringStack = false;
        printf("Finished stack.\n");
    }
}

void MainWindow::ZStackTakeNextStep()
{
    //registered callback, every 3 seconds from stack start.
    //double current_z_position_microns = mTrinamic->CurrentPositionMicrons[mTrinamic->ZMotor];

    //Rotated = non-rotated for XZAngle = 0;
    double current_z_position_microns = mTrinamic->CurrentPositionRotated[mTrinamic->ZMotor];

    //ZStack acquisition
    //timer callback.  this is called every say 3000 seconds.
    if (nZStackCurrentSlice < nZStackTotalSlices)
    {
        mTrinamic->MoveToPosition(mTrinamic->ZMotor, current_z_position_microns + dZStackPitch);
        Sleep(nMotionSettleMillseconds);

        if(!bResonantScanning)
        {
            //not resonant scanning, send trigger to scan image
            //if pinout version = 1, ie portera lab system
            //doesn't actually change the port
            mNationalInstruments->OutputDigitalPulse("Dev1/Port2/Line5", 1);
        }
        else
        {
            //resonant scanning, start acquisition
        }
        printf("Acquiring stack slice %d\n", nZStackCurrentSlice); //else if pinout version = 2, ie all others...
        nZStackCurrentSlice++;
    }
    else if(nZStackCurrentSlice >= nZStackTotalSlices) StopZStack();
}

void MainWindow::UpdatePreciseStack()
{
    ui->doubleSpinBox_micronperslice_2->setValue(
                (ui->doubleSpinBox_depthend->value() - ui->doubleSpinBox_depthstart->value()) /
                ui->spinBox_totalzslices_precise->value()
                );
}

void MainWindow::AcquireZStack_Precise(double ZPitchMicrons, int nFrames)
{

    //mTrinamic->MoveToPosition(mTrinamic->ZMotor, dPreciseStackStart);

    nZStackCurrentSlice = 0;
    nZStackTotalSlices = ui->spinBox_totalzslices_precise->value();
    dZStackPitch = ui->doubleSpinBox_micronperslice_2->value();
    ui->checkBox_savemonitor->setChecked(true);
    mMatroxImagingLibrary->bSaveMonitor = true;
    ui->AcquisitionGroup->setDisabled(true);

    //calculate laser power ramp
    float start = ui->doubleSpinBox_powerstart->value();
    float end = ui->doubleSpinBox_powerend->value();


    //mMatroxImagingLibrary->bAppendPrev = true;

    if(1)
    {
        QString temp;

        double depth = -2500.0;
        double maxspeed = 2.0;
        double pitch = 800.0;

        //mTrinamic->SetMaximumSpeed(mTrinamic->ZMotor,25);
        //mTrinamic->SetMaximumSpeed(mTrinamic->XMotor,100);
        //mTrinamic->SetMaximumSpeed(mTrinamic->YMotor,100);

        //move to start
        temp.sprintf("move %f %f %f",
                     mTrinamic->CurrentPositionRotated[mTrinamic->XMotor],
                     mTrinamic->CurrentPositionRotated[mTrinamic->YMotor],
                     dPreciseStackStart
                     );
        CurrentScript.push_back(temp);

        for(int i=0; i<nZStackTotalSlices; i++)
        {
            //move to next position
            temp.sprintf("move %f %f %f",
                         mTrinamic->CurrentPositionRotated[mTrinamic->XMotor],
                         mTrinamic->CurrentPositionRotated[mTrinamic->YMotor],
                         dPreciseStackStart + dZStackPitch*(i+1)
                         );
            CurrentScript.push_back(temp);

            //change laser power
            double progress = double(i)/double(nZStackTotalSlices);
            float newlaser = progress*(ui->doubleSpinBox_powerend->value()) + (1.0-progress)* (ui->doubleSpinBox_powerstart->value());
            //UpdateZoom(-1,-1,newlaser);
            temp.sprintf("changelaserpower %f %f %f",
                         newlaser, 0.0, 0.0);
            CurrentScript.push_back(temp);

            //start monitor
            temp.sprintf("monitor %f %f %f",
                         0.0, 0.0, 0.0);
            CurrentScript.push_back(temp);
        }


        //start monitor
        temp.sprintf("finishprecisestack %f %f %f",
                     0.0, 0.0, 0.0);
        CurrentScript.push_back(temp);

    }

    bWaitingForLastFinish = false;

    printf("Starting Precise Z Stack Script\n");
    for(int i = 0; i < CurrentScript.size(); i++)
    {
        printf("%s\n",CurrentScript[i].toLocal8Bit().data());
    }

    //script will run until empty, and stop its timer
    bRunningScript = true;
    mTimerScript.start(300);
    bAcquiringStack_Precise = true;
    return;
}

void MainWindow::StopZStack_Precise()
{
    ScriptFlush();
    bAcquiringStack_Precise = false;
    bWaitingForLastFinish = false;
    //mMatroxImagingLibrary->bAppendPrev = false;
    this->UpdateInterface();
    printf("Script: Aborted precise stack\n");

}

void MainWindow::StopMosaic()
{
    ScriptFlush();
    bWaitingForLastFinish = false;
    //mMatroxImagingLibrary->bAppendPrev = false;
    this->UpdateInterface();
    printf("Script: Aborted mosaic\n");
    bAcquiringMosaic = false;
}

void MainWindow::Acquire2DMosaic(int imagesx, int imagesy, double stridex, double stridey)
{
    ui->checkBox_savemonitor->setChecked(true);
    mMatroxImagingLibrary->bSaveMonitor = true;
    ui->AcquisitionGroup->setDisabled(true);

    QString temp;


    //move to start
    temp.sprintf("move %f %f %f",
                 mTrinamic->CurrentPositionRotated[mTrinamic->XMotor],
                 mTrinamic->CurrentPositionRotated[mTrinamic->YMotor],
                 dPreciseStackStart
                 );
    CurrentScript.push_back(temp);

    for(int i = 0; i < imagesx; i++)
    {
        for(int j = 0; j < imagesy; j++)
        {

            //move to next position
            temp.sprintf("move %f %f %f",
                         mTrinamic->CurrentPositionRotated[mTrinamic->XMotor] + i*stridex,
                         mTrinamic->CurrentPositionRotated[mTrinamic->YMotor] + j*stridey,
                         mTrinamic->CurrentPositionRotated[mTrinamic->ZMotor]
                         );
            CurrentScript.push_back(temp);


            //start monitor
            temp.sprintf("monitor %f %f %f",
                         0.0, 0.0, 0.0);
            CurrentScript.push_back(temp);
        }
    }

    //move back to origin
    temp.sprintf("move %f %f %f",
                 mTrinamic->CurrentPositionRotated[mTrinamic->XMotor],
                 mTrinamic->CurrentPositionRotated[mTrinamic->YMotor],
                 mTrinamic->CurrentPositionRotated[mTrinamic->ZMotor]
                 );
    CurrentScript.push_back(temp);

    bWaitingForLastFinish = false;

    printf("Starting 2d mosaic Script\n");
    for(int i = 0; i < CurrentScript.size(); i++)
    {
        printf("%s\n",CurrentScript[i].toLocal8Bit().data());
    }

    //script will run until empty, and stop its timer
    bAcquiringMosaic = true;
    bRunningScript = true;
    mTimerScript.start(300);

    return;
}

void MainWindow::Acquire3DMosaic(int imagesx, int imagesy, int imagesz, double stridex, double stridey, double stridez, double startpower, double endpower)
{
    ui->checkBox_savemonitor->setChecked(true);
    mMatroxImagingLibrary->bSaveMonitor = true;
    ui->AcquisitionGroup->setDisabled(true);

    QString temp;

    for(int i = 0; i < imagesx; i++)
    {
        for(int j = 0; j < imagesy; j++)
        {
            for(int k = 0; k < imagesz; k++)
            {

                //move to next position
                temp.sprintf("move %f %f %f",
                             mTrinamic->CurrentPositionRotated[mTrinamic->XMotor] + i*stridex,
                             mTrinamic->CurrentPositionRotated[mTrinamic->YMotor] + j*stridey,
                             mTrinamic->CurrentPositionRotated[mTrinamic->ZMotor] + k*stridez
                             );
                CurrentScript.push_back(temp);

                //change laser power
                double progress = double(k)/double(imagesz);
                float newlaser = progress*(startpower) + (1.0-progress)* (endpower);
                temp.sprintf("changelaserpower %f %f %f",
                             newlaser, 0.0, 0.0);
                CurrentScript.push_back(temp);

                //start monitor
                temp.sprintf("monitor %f %f %f",
                             0.0, 0.0, 0.0);
                CurrentScript.push_back(temp);
            }
        }
    }

    //move back to origin
    temp.sprintf("move %f %f %f",
                 mTrinamic->CurrentPositionRotated[mTrinamic->XMotor],
                 mTrinamic->CurrentPositionRotated[mTrinamic->YMotor],
                 mTrinamic->CurrentPositionRotated[mTrinamic->ZMotor]
                 );
    CurrentScript.push_back(temp);

    bWaitingForLastFinish = false;

    printf("Starting 3D mosaic Script\n");
    for(int i = 0; i < CurrentScript.size(); i++)
    {
        printf("%s\n",CurrentScript[i].toLocal8Bit().data());
    }

    //script will run until empty, and stop its timer
    bAcquiringMosaic = true;
    bRunningScript = true;
    mTimerScript.start(300);
    return;

}

void MainWindow::Acquire3DMosaicFast(int imagesx, int imagesy, double zstart, double zend, double stridex, double stridey, int zspeed, double startpower, double endpower)
{
    ui->checkBox_savemonitor->setChecked(true);
    mMatroxImagingLibrary->bSaveMonitor = true;
    ui->AcquisitionGroup->setDisabled(true);

    QString temp;


    //move to start
    temp.sprintf("move %f %f %f",
                 mTrinamic->CurrentPositionRotated[mTrinamic->XMotor],
                 mTrinamic->CurrentPositionRotated[mTrinamic->YMotor],
                 zstart
                 );
    CurrentScript.push_back(temp);

    for(int i = 0; i < imagesx; i++)
    {
        for(int j = 0; j < imagesy; j++)
        {

            //move to next position
            temp.sprintf("move %f %f %f",
                         mTrinamic->CurrentPositionRotated[mTrinamic->XMotor] + i*stridex,
                         mTrinamic->CurrentPositionRotated[mTrinamic->YMotor] + j*stridey,
                         zstart
                         );
            CurrentScript.push_back(temp);


            //start fast stack
            temp.sprintf("faststack %f %f %f",
                         zend, double(zspeed), 0.0);
            CurrentScript.push_back(temp);
        }
    }

    //move back to origin
    temp.sprintf("move %f %f %f",
                 mTrinamic->CurrentPositionRotated[mTrinamic->XMotor],
                 mTrinamic->CurrentPositionRotated[mTrinamic->YMotor],
                 zstart
                 );
    CurrentScript.push_back(temp);

    bWaitingForLastFinish = false;

    printf("Starting 3d mosaic fast Script\n");
    for(int i = 0; i < CurrentScript.size(); i++)
    {
        printf("%s\n",CurrentScript[i].toLocal8Bit().data());
    }

    //script will run until empty, and stop its timer
    bAcquiringMosaic = true;
    bRunningScript = true;
    mTimerScript.start(300);

    return;
}

void MainWindow::AcquireZStack_Fast(double depth, int speed)
{

    ui->checkBox_savemonitor->setChecked(true);
    mMatroxImagingLibrary->bSaveMonitor = true;
    //ui->AcquisitionGroup->setDisabled(true);

    bAcquiringStack_Fast = true;

    if(bResonantScanning)
    {
        UpdateMatrox();
        UpdateFilename();

        if(!mMatroxImagingLibrary->bMonitoring)
        {
            StartMonitor();
            //ui->pushButtonMonitor->setText("Stop Monitor-Fast Stack");
            //ui->pushButton_precisezstack->setText("Stop Stack");
        }
    }

    mTrinamic->SetMaximumSpeed(mTrinamic->ZMotor, speed);
    mTrinamic->MoveToPosition(mTrinamic->ZMotor, depth);

    //Starts timer with 3 second hardcoded delay, and waits for callback
    //mTimerStack.start(nAcquisitionTimeMilliseconds);
    printf("Stack: Starting fast stack.\n");
    return;
}

void MainWindow::ScriptEngine()
{
    //check if we should do the next command
    if(!bWaitingForLastFinish)
    {
        if(CurrentScript.length() == 0)
        {
            //finished script
            printf("Script: no more items, finished\n");
            mTimerScript.stop();

            bAcquiringMosaic = false;
            bAcquiringStack_Precise = false;
            bAcquiringStack_Fast = false;
            UpdateInterface();
            return;
        }

        //do next cmd, extracted from current script list
        QString temp = CurrentScript[0];
        double dA, dB, dC;
        CurrentScript.pop_front();
        QString cmd;
        QTextStream mystream;
        mystream.setString(&temp);
        mystream >> cmd;
        mystream >> dA;
        mystream >> dB;
        mystream >> dC;

        //execute
        printf("Script: doing %s\n", temp.toLocal8Bit().data());
        ScriptCmd(cmd, dA, dB, dC);

        //store last command
        LastCommand = cmd;
        LastdA = dA;
        LastdB = dB;
        LastdC = dC;
    }
    else
    {
        //FIGURE OUT IF VARIOUS TASKS HAVE COMPLETED

        if(LastCommand == "move")
        {
            double difa, difb, difc;
            difa = abs(mTrinamic->CurrentPositionRotated[mTrinamic->XMotor] - LastdA);
            difb  = abs(mTrinamic->CurrentPositionRotated[mTrinamic->YMotor] - LastdB);
            difc  = abs(mTrinamic->CurrentPositionRotated[mTrinamic->ZMotor] - LastdC);

            printf("Script: dif %f %f %f\n",difa, difb, difc);

            double tolerance = 2.0;
            if(difa < tolerance && difb < tolerance && difc < tolerance)
            {
                //finished move within tolerance
                //reset counter, or just continue with next move
                bWaitingForLastFinish = false;
                this->UpdateInterface();
                ScriptEngine();
            }

        }
        else if(LastCommand == "thetaradius" || LastCommand == "theta")
        {
            if(mTrinamic->MoveFinished())
            {
                bWaitingForLastFinish = false;
                this->UpdateInterface();
                ScriptEngine();
            }
        }
        else if(LastCommand == "faststack")
        {
            if(!mMatroxImagingLibrary->bMonitoring || mTrinamic->MoveFinished())
            {
                if(mTrinamic->MoveFinished()) mMatroxImagingLibrary->StopMonitor();
                mTrinamic->RestoreMaximumSpeed();
                //probably finished the stack
                bAcquiringStack_Fast = false;
                bWaitingForLastFinish = false;
                this->UpdateInterface();
                ScriptEngine();
            }
        }
        else if(LastCommand == "monitor")
        {
            if(!mMatroxImagingLibrary->bMonitoring)
            {
                bWaitingForLastFinish = false;
                ScriptEngine();
            }
        }
        else if(LastCommand == "acquire")
        {
            if(!mMatroxImagingLibrary->bAcquiring)
            {
                bWaitingForLastFinish = false;
                ScriptEngine();
            }
        }
    }

}

void MainWindow::ScriptFlush()
{
    printf("Flushing script.\n");
    bWaitingForLastFinish = false;

    CurrentScript.clear();

    if(this->bMatrox)
    {
        if(mMatroxImagingLibrary->bAcquiring)
        {
            this->StopAcquire();
        }
        if(mMatroxImagingLibrary->bMonitoring)
        {
            this->StopMonitor();
        }
    }

    return;
}

void MainWindow::ScriptCmd(QString cmd, double dA, double dB, double dC)
{
    if(cmd == "move")
    {
        //move motors
        mTrinamic->SetMaximumSpeed(mTrinamic->XMotor, 800.0);
        mTrinamic->SetMaximumSpeed(mTrinamic->YMotor, 800.0);
        mTrinamic->SetMaximumSpeed(mTrinamic->ZMotor, 100.0);
        mTrinamic->MoveToPosition(
                    mTrinamic->XMotor, dA,
                    mTrinamic->YMotor, dB,
                    mTrinamic->ZMotor, dC );

        //since this is an asynchronous action, need to wait before proceeding
        bWaitingForLastFinish = true;
        printf("Script: Did move cmd\n");

    }
    if(cmd == "moverel")
    {
        //move motors
        mTrinamic->MoveDeltaPosition(
                    mTrinamic->XMotor, dA,
                    mTrinamic->YMotor, dB,
                    mTrinamic->ZMotor, dC );

        //since this is an asynchronous action, need to wait before proceeding
        bWaitingForLastFinish = true;
        printf("Script: Did move cmd\n");

    }
    if(cmd == "theta")
    {
        //move motors
        mTrinamic->MoveToAngleRelative(dA);
        //since this is an asynchronous action, need to wait before proceeding
        bWaitingForLastFinish = true;
        printf("Script: Did move cmd\n");

    }
    if(cmd == "thetaradius")
    {
        //move motors
        mTrinamic->MoveThetaRadius(dA);
        //since this is an asynchronous action, need to wait before proceeding
        bWaitingForLastFinish = true;
        printf("Script: Did move cmd\n");

    }
    else if(cmd == "faststack")
    {
        AcquireZStack_Fast(dA, dB);
        bWaitingForLastFinish = true;
        printf("Script: Started fast zstack\n");
    }
    else if(cmd == "monitor")
    {
        StartMonitor();
        bWaitingForLastFinish = true;
        printf("Script: Started monitor\n");
    }
    else if(cmd == "acquire")
    {
        StartAcquire();
        bWaitingForLastFinish = true;
        printf("Script: Started acquire\n");
    }
    else if(cmd == "changelaserpower")
    {
        UpdateZoom(-1,-1,dA);
        bWaitingForLastFinish = false;
        printf("Script: Changed laser power\n");
    }
    else if(cmd == "numberframes")
    {
        mMatroxImagingLibrary->nFramesPerFile = int(dA);
        ui->spinBox_frames->setValue(mMatroxImagingLibrary->nFramesPerFile);
        bWaitingForLastFinish = false;
        printf("Script: Changed number of frames\n");
    }
    else if(cmd == "datasetprefix")
    {
        QString mytemp;
        mMatroxImagingLibrary->sFilebase = mytemp.sprintf("%05d_",int(dA)) + mMatroxImagingLibrary->sFilebase;
        mMatroxImagingLibrary->UpdateFilename();
        this->UpdateFilenameToUi();
        bWaitingForLastFinish = false;
        printf("Script: Changed dataset prefix\n");
    }
    else if(cmd == "externaltriggeron")
    {
        SetExtTrigger(true);
        bWaitingForLastFinish = false;
        printf("Script: set ext trigger on\n");
    }
    else if(cmd == "externaltriggeroff")
    {
        SetExtTrigger(false);
        bWaitingForLastFinish = false;
        printf("Script: set ext trigger off\n");
    }
    else if(cmd == "retriggeron")
    {

        SetRetrigger(true);
        bWaitingForLastFinish = true;
        printf("Script: set retrigger on\n");
    }
    else if(cmd == "retriggeroff")
    {

        SetRetrigger(false);
        bWaitingForLastFinish = false;
        printf("Script: set retrigger off\n");
    }
    else if(cmd == "savemonitoron")
    {

        ui->checkBox_savemonitor->setChecked(true);
        mMatroxImagingLibrary->bSaveMonitor = true;
        bWaitingForLastFinish = false;
        printf("Script: Changed save monitor\n");
    }
    else if(cmd == "savemonitoroff")
    {
        ui->checkBox_savemonitor->setChecked(false);
        mMatroxImagingLibrary->bSaveMonitor = false;
        bWaitingForLastFinish = false;
        printf("Script: Changed save monitor\n");
    }
    else if(cmd == "finishprecisestack")
    {
        bAcquiringStack_Precise = false;
        bWaitingForLastFinish = false;

        //mMatroxImagingLibrary->bAppendPrev = false;
        this->UpdateInterface();
        printf("Script: Finished precise stack\n");
    }
    else
    {
        printf("Script: Unrecognized command, ignored.\n");
    }


    return;
}

//example script

void MainWindow::SetExtTrigger(bool trig)
{
    mMatroxImagingLibrary->bRetrigger = trig;
    ui->checkBox_retriggerable->setChecked(trig);
}
void MainWindow::SetRetrigger(bool trig)
{
    mMatroxImagingLibrary->bRetrigger = trig;
    ui->checkBox_retriggerable->setChecked(trig);
}


void MainWindow::OnMove(std::vector<float>& motionData)
{
        //check if the data is bad
        if (motionData.size() < 6) return;

        //debug output
        //ui->debug_x->setText( QString::number(motionData[0]) );
        //ui->debug_y->setText( QString::number(motionData[1]) );
        //ui->debug_z->setText( QString::number(motionData[2]) );
        //ui->debug_rx->setText( QString::number(motionData[3]) );
        //ui->debug_ry->setText( QString::number(motionData[4]) );
        //ui->debug_rz->setText( QString::number(motionData[5]) );


        QDebug(QtDebugMsg) << "Motion." << endl;

        //Do motion and serial port control here
        if(bCommPortOpen)
        {
            //send control to the Trinamic controller class
            mTrinamic->ProcessControllerMove(motionData);
        }
        else
        {
            //no serial port
            2;
        }
}

void MainWindow::LoadPowerCalibration()
{
    printf("Choose calibration text file\n");

    QString fileName = QFileDialog::getOpenFileName(this,
         tr("Open calibration text file"), "//", tr("Text File (*.txt)"));

    printf("Opened calibration file %s\n", fileName.toLocal8Bit().data());

    QFile qPowerFile(fileName);

    if( !qPowerFile.open(QIODevice::ReadWrite | QIODevice::Text) )
    {
        printf("Failed to write acquisition parameters \n");
    }

    QTextStream in(&qPowerFile);
    in.reset();

    double dVoltages[10];

    for (int i = 0; i < 10; i++)
    {
        in >> dVoltages[i] >> dPowerCalibration[i] >> endl;
        printf("%d %f %f\n",i,dVoltages[i],dPowerCalibration[i]);
    }

    qPowerFile.close();

    printf("Finished.\n");
    DoPowerCalibration();
    UpdateInterface();

    /*
    QFileDialog dialog(this);
    //dialog.set
    dialog.setFileMode(QFileDialog::ExistingFile);
    //dialog.setOption(QFileDialog::ShowDirsOnly, true);

    dialog.setDirectory("C:\\");//mMatroxImagingLibrary->sFilepath);
    QStringList fileNames;

     if (dialog.exec())
     {
         fileNames = dialog.selectedFiles();

         //ui->lineEdit_pathname->setText(fileNames.first() + '/');
         //UpdateFilename();
     }
     */
}

void MainWindow::DoPowerCalibration()
{

    double index =  mNationalInstruments->dLaserPower*10;

    //get nearest integers
    int lower = int(floor(index));
    int higher = int(ceil(index));

    //keep within bounds
    lower = max(min(lower,9),0);
    higher = max(min(higher,9),0);

    double fraction = index - lower;

    //interpolate power
    double thepower = (1.0-fraction)*this->dPowerCalibration[lower]+ fraction*dPowerCalibration[higher];

    ui->doubleSpinBox_laserpowercalibrated->setValue(thepower);

    printf("Updated calibrated laser power\n");

    return;
}

void MainWindow::Retract()
{

    if(nRetractCount < 2)
    {
        nRetractCount++;
        printf("Rectraction pushed. One more time...\n");
    }
    else
    {

        printf("Retracting objective by %d mm...\n", dRetraction);
        mTrinamic->MoveDeltaPosition(
                    mTrinamic->XMotor,0.0,
                    mTrinamic->YMotor,0.0,
                    mTrinamic->ZMotor,dRetraction*1000
                    );

        nRetractCount = 0;
    }
    return;
}

void MainWindow::PositionQuery()
{

    //check if the controller was turned off.  if so, attempt reconnect
    if(mTrinamic->nErrorCount > 1000)
    {
        printf("Position query: Potentially the motion control system is not powered.\n");
        //printf("Position query: Please turn on power, and we will re-attempt to communicate.\n");
        //ShutdownTrinamic();
        //InitializeTrinamic(false);

    }

    mTrinamic->PositionQuery();

    double display_position[6];
    double display_origin[6];
    double display_stackstart = dPreciseStackStart;
    double display_stackend = dPreciseStackFinish;

    for(int i = 0; i < 3; i++)
    {
        if(mTrinamic->bRotationMode)
        {
            display_position[i] = mTrinamic->CurrentPositionRotated[i];
            display_origin[i] = mTrinamic->RotationModeRelativeOrigin[i];
        }
        else
        {
            display_position[i] = mTrinamic->CurrentPositionMicrons[i];
            display_origin[i] = mTrinamic->RelativeModeOrigin[i];
        }

        if(!mTrinamic->bRelativeMode)
        {
            display_origin[i] = 0;
        }

        //continue to round for display purposes
        display_position[i] = ceil(
                    (display_position[i]-display_origin[i])
                    *100.0)/100.0;
        //send to display
        //depending on the mode
    }


    //in the future this will be decoupled
    double angle_display = mTrinamic->XZRotationAngle*180.0/3.1415926;

    //display angle
    ui->lcdNumber_4->display(angle_display);

    //display x y z
    ui->lcdNumber->display(display_position[mTrinamic->XMotor]);
    ui->lcdNumber_2->display(display_position[mTrinamic->YMotor]);
    ui->lcdNumber_Z->display(display_position[mTrinamic->ZMotor]);

    ui->doubleSpinBox_depthstart->setValue(display_stackstart-display_origin[mTrinamic->ZMotor]);
    ui->doubleSpinBox_depthend->setValue(display_stackend-display_origin[mTrinamic->ZMotor]);

    //give imaging object the position, for log files etc
    if(bMatrox)
    {
        mMatroxImagingLibrary->dPositionMicrons[0] = mTrinamic->CurrentPositionRotated[mTrinamic->XMotor];
        mMatroxImagingLibrary->dPositionMicrons[1] = mTrinamic->CurrentPositionRotated[mTrinamic->YMotor];
        mMatroxImagingLibrary->dPositionMicrons[2] = mTrinamic->CurrentPositionRotated[mTrinamic->ZMotor];
    }

}

void MainWindow::SetMagnification(int mag)
{

    if(!bResonantScanning)
    {
        printf("Mag not relevant - not resonant scanning.\n");
        return;
    }

    int nX = mMatroxImagingLibrary->UserHookData.nSizeX/2/mMatroxImagingLibrary->nHorizontalDownsample;
    int nY = mMatroxImagingLibrary->UserHookData.nSizeY*2;

    double greater;
    double lesser;
    bool xgreater = false;

    if (nX >= nY)
    {
        xgreater = true;
        greater = nX;
        lesser = nY;
    }
    else
    {
        greater = nY;
        lesser = nX;
    }

    //assumes voltage to angle is the same for fast/slow axes
    double greater_scan = 1.0/mag;
    double lesser_scan = double(lesser)/double(greater)/mag;

    if(xgreater)
    {
        //if the x dimension of the image is greater, then set fast axis to larger of the two
        UpdateZoom(greater_scan, lesser_scan, -1);
    }
    else
    {
        UpdateZoom(lesser_scan, greater_scan, -1);
    }


}

//bug: potentially infinite loop, crash on slide occasionally
void MainWindow::UpdateZoom(double fast, double slow, double laser)
{
    printf("Updating Zoom\n");
    //int extra = ui->spinBox_extrazoom->value();
    //mNationalInstruments->nExtraZoom = extra;

    //don't change for fast -1
    if(fast >= 0.0)
    {
        ui->doubleSpinBox_fastzoom->setValue(fast);
        mNationalInstruments->dXScanFraction = fast;
    }
    //don't change for slow -1
    if(slow >= 0.0)
    {
        ui->doubleSpinBox_slowzoom->setValue(slow);
        mNationalInstruments->dYScanFraction = slow;
    }
    //don't change laser if laser -1
    if(laser >= 0.0)
    {
        ui->doubleSpinBox_laserpower->setValue(laser);
        mNationalInstruments->dLaserPower = laser;
        DoPowerCalibration();
        UpdateInterface();
    }

    if(mNationalInstruments->bResonantScanning && bInitialized)
    {
        printf("Restart scanning\n");
        if(mMatroxImagingLibrary->bMonitoring) mNationalInstruments->CloseShutter(0);
        mNationalInstruments->StopResonantScanning();
        mNationalInstruments->StartResonantScanning();
        if(mMatroxImagingLibrary->bMonitoring) mNationalInstruments->OpenShutter(0);
    }
    else if(!bInitialized)
    {
        printf("Too early to start scanning.\n");
    }
    else
    {
        printf("Skipped zoom update - not resonant scanning.\n");
    }
}

void MainWindow::UpdateMatrox()
{

    printf("Function: Update Matrox\n");
    //any of these require re-initialization?
    //intended to call this before a monitor click

    mMatroxImagingLibrary->bMonitoring;
    mMatroxImagingLibrary->bAcquiring;
    mMatroxImagingLibrary->bInvert = ui->checkBoxInvert->checkState();
    mMatroxImagingLibrary->bLog = ui->checkBoxLog->checkState();
    mMatroxImagingLibrary->bMeanConvolve = ui->checkBoxMean->checkState();
    mMatroxImagingLibrary->bMedianConvolve = ui->checkBoxMedian->checkState();
    mMatroxImagingLibrary->bMerge = ui->checkBoxMerge->checkState();
    mMatroxImagingLibrary->bColor = ui->checkBoxColor->checkState();
    mMatroxImagingLibrary->bExtTrigger = ui->checkBox_exttrigger->checkState();
    mMatroxImagingLibrary->bRetrigger = ui->checkBox_retriggerable->checkState();
    mMatroxImagingLibrary->bSaveMonitor = ui->checkBox_savemonitor->checkState();

    mMatroxImagingLibrary->bWarp = ui->checkBoxSine->checkState();
    //mMatroxImagingLibrary->bFlipRes = ui->checkBoxSine->checkState();
    mMatroxImagingLibrary->bFlipX = false;
    mMatroxImagingLibrary->bFlipY = false;
    mMatroxImagingLibrary->nSummationTotal = ui->spinBox_sumframes->value();
    //mMatroxImagingLibrary->nHorizontalDownsample = ui->spinBox_sumpixels->value();

    mMatroxImagingLibrary->nMin[0] = ui->spinBox_min_1->value();
    mMatroxImagingLibrary->nMax[0] = ui->spinBox_max_1->value();
    mMatroxImagingLibrary->dADCMax[0] = ui->doubleSpinBox_gain1->value();
    mMatroxImagingLibrary->dADCMin[0] = ui->doubleSpinBox_gain1_2->value();
    mMatroxImagingLibrary->nMin[1] = ui->spinBox_min_2->value();
    mMatroxImagingLibrary->nMax[1] = ui->spinBox_max_2->value();
    mMatroxImagingLibrary->dADCMax[1] = ui->doubleSpinBox_gain2->value();
    mMatroxImagingLibrary->dADCMin[1] = ui->doubleSpinBox_gain2_2->value();
    mMatroxImagingLibrary->nMin[2] = ui->spinBox_min_3->value();
    mMatroxImagingLibrary->nMax[2] = ui->spinBox_max_3->value();
    mMatroxImagingLibrary->dADCMax[2] = ui->doubleSpinBox_gain3->value();
    mMatroxImagingLibrary->dADCMin[2] = ui->doubleSpinBox_gain3_2->value();

    //mMatroxImagingLibrary->UpdateLUT();
    //mMatroxImagingLibrary->UpdateGain();
    //mMatroxImagingLibrary->UpdateCouplingMode();
}


void MainWindow::UpdateROIPlots(double* list)
{
    printf("Plotting ROI traces...\n");
    for(int i = 0; i<24; i++)
    {
        plotvector[i].push_back(list[i] + i*3);
        plotvector[i].pop_front();
        pw->myplot->graph(i)->setData(plotvectorx, plotvector[i]);
        if(i==0)
        pw->myplot->graph(i)->rescaleAxes();
        else
        pw->myplot->graph(i)->rescaleAxes(true);
    }

    pw->myplot->replot();
}


void MainWindow::UpdateHistogramPlots(double *red, double *green, double *blue)
{

    printf("Plotting Histograms (Raw 0-255)...\n");

    for(int i=0;i<HIST_VALUE;i++)
    {
        plothistogram[0][i] = log(red[i]+1);
        plothistogram[1][i] = log(green[i]+1);
        plothistogram[2][i] = log(blue[i]+1);

    }

    pw->myhistogram->graph(0)->setData(plothistogramx, plothistogram[0]);
    pw->myhistogram->graph(0)->rescaleAxes();
    pw->myhistogram->graph(1)->setData(plothistogramx, plothistogram[1]);
    pw->myhistogram->graph(1)->rescaleAxes();
    pw->myhistogram->graph(2)->setData(plothistogramx, plothistogram[2]);
    pw->myhistogram->graph(2)->rescaleAxes();
    pw->myhistogram->xAxis->setRange(0, 255);
    pw->myhistogram->replot();
    delete [] red;
    delete [] green;
    delete [] blue;


}

void MainWindow::keyPressEvent(QKeyEvent * e)
{

    if(!(e->isAutoRepeat()))
    {
        HandleKeyboardEvent(e, true, false);
    }
    QMainWindow::keyPressEvent(e);

}

void MainWindow::keyReleaseEvent(QKeyEvent * e)
{

    if(!(e->isAutoRepeat()))
    {
        HandleKeyboardEvent(e, false, false);
    }
    QMainWindow::keyReleaseEvent(e);
}

void MainWindow::HandleKeyboardEvent(QKeyEvent * e, bool down, bool externalcapture)
{

    //QDebug(QtDebugMsg) << "Keypress " << e->key() << endl;

    int key = e->key();

    if ((e->modifiers() & Qt::ControlModifier) && externalcapture)
    {
        //control key pressed.
        //QDebug(QtDebugMsg) << "Control Key." << endl;


        if (key == nKeymap[KEY_XWHEELPOS])
        {
            if (down) mTrinamic->TakeStrides(mTrinamic->XMotor, 1);
        }
        else if( key == nKeymap[KEY_XWHEELNEG])
        {
            if (down) mTrinamic->TakeStrides(mTrinamic->XMotor, -1);
        }
        else if( key == nKeymap[KEY_YWHEELPOS])
        {
            if (down) mTrinamic->TakeStrides(mTrinamic->YMotor, 1);
        }
        else if( key == nKeymap[KEY_YWHEELNEG])
        {
            if (down) mTrinamic->TakeStrides(mTrinamic->YMotor, -1);
        }
        else if( key == nKeymap[KEY_ZWHEELPOS])
        {
            if (down) mTrinamic->TakeStrides(mTrinamic->ZMotor, 1);
        }
        else if( key == nKeymap[KEY_ZWHEELNEG])
        {
            if (down) mTrinamic->TakeStrides(mTrinamic->ZMotor, -1);
        }


    }
    else
    {

        //shift, alt or other key


        //The keys below activate velocity mode motion, for keyboard or joystick style input

        if(key == nKeymap[KEY_XNEG])
        {

            if (down) mTrinamic->SetVelocityBin(mTrinamic->XMotor,-3);
            else mTrinamic->SetVelocityBin(mTrinamic->XMotor,0);
        }

        else if (key == nKeymap[KEY_XPOS])
        {

            if (down) mTrinamic->SetVelocityBin(mTrinamic->XMotor,3);
            else mTrinamic->SetVelocityBin(mTrinamic->XMotor,0);

        }

        else if (key == nKeymap[KEY_YPOS])
        {

            if (down) mTrinamic->SetVelocityBin(mTrinamic->YMotor,3);
            else mTrinamic->SetVelocityBin(mTrinamic->YMotor,0);

        }

        else if (key == nKeymap[KEY_YNEG])
        {

            if (down) mTrinamic->SetVelocityBin(mTrinamic->YMotor,-3);
            else mTrinamic->SetVelocityBin(mTrinamic->YMotor,0);

        }

        else if (key == nKeymap[KEY_ZNEG])
        {

            if (down) mTrinamic->SetVelocityBin(mTrinamic->ZMotor,-3);
            else mTrinamic->SetVelocityBin(mTrinamic->ZMotor,0);

        }

        else if (key == nKeymap[KEY_ZPOS])
        {

            if (down) mTrinamic->SetVelocityBin(mTrinamic->ZMotor,3);
            else mTrinamic->SetVelocityBin(mTrinamic->ZMotor,0);

        }
        else if (key == nKeymap[KEY_TNEG])
        {

            if (down) mTrinamic->SetVelocityBin(mTrinamic->ThetaMotor,-1);
            else mTrinamic->SetVelocityBin(mTrinamic->ThetaMotor,0);

        }

        else if (key == nKeymap[KEY_TPOS])
        {

            if (down) mTrinamic->SetVelocityBin(mTrinamic->ThetaMotor,1);
            else mTrinamic->SetVelocityBin(mTrinamic->ThetaMotor,0);

        }
        else if (key == nKeymap[KEY_TTNEG])
        {

            if (down) mTrinamic->MoveThetaRadius(-0.01/mTrinamic->CurrentCoarseFineSetting);
            else 1;

        }

        else if (key == nKeymap[KEY_TTPOS])
        {

            if (down) mTrinamic->MoveThetaRadius(0.01/mTrinamic->CurrentCoarseFineSetting);
            else 1;

        }
    }

    return;
}


void MainWindow::StartMonitor()
{

    if(!bMatrox) return;
    UpdateMatrox();
    //UpdateFilename();
    mMatroxImagingLibrary->UserHookData.mMainWindow = this;
    mNationalInstruments->OpenShutter(0);
    mMatroxImagingLibrary->StartMonitor();

    if(mMatroxImagingLibrary->bSaveMonitor)
        ui->pushButtonMonitor->setText("Stop Monitor (saving)");
    else
        ui->pushButtonMonitor->setText("Stop Monitor");


    UpdateInterface();


}

void MainWindow::StopMonitor()
{

    if(!bMatrox) return;
    mNationalInstruments->CloseShutter(0);
    mMatroxImagingLibrary->StopMonitor();
    ui->pushButtonMonitor->setText("Monitor");

    if(mMatroxImagingLibrary->bSaveMonitor)
        this->OutputReport(1);

    UpdateInterface();

}

void MainWindow::StartAcquire()
{

    if(!bMatrox) return;
    UpdateMatrox();
    //UpdateFilename();
    mMatroxImagingLibrary->UserHookData.mMainWindow = this;
    if(!mMatroxImagingLibrary->bExtTrigger) mNationalInstruments->OpenShutter(0);
    //else, open trigger on start only
    mMatroxImagingLibrary->StartAcquisition();

    UpdateInterface();
}

void MainWindow::StopAcquire()
{
    if(!bMatrox) return;

    mNationalInstruments->CloseShutter(0);
    mMatroxImagingLibrary->StopAcquisition();


    OutputReport(0);

    UpdateInterface();
}

void MainWindow::SaveDelay()
{

    QString arg1 = ui->comboBox_magnification->currentText();
    int pulsedelay = mNationalInstruments->nPulseDelay;
    double dFastDelay = mNationalInstruments->dFastBlankDelay;
    double dFastFreq = mNationalInstruments->dFastFreq;
    if(arg1 == QString("1x"))
    {
        mNationalInstruments->nPulseDelay1x = pulsedelay;
        mNationalInstruments->dFastBlankDelay1x = dFastDelay;
        mNationalInstruments->dFastFreq1x = dFastFreq;
    }
    if(arg1 == QString("2x"))
    {
         mNationalInstruments->nPulseDelay2x = pulsedelay;
         mNationalInstruments->dFastBlankDelay2x = dFastDelay;
         mNationalInstruments->dFastFreq2x = dFastFreq;
     }
    if(arg1 == QString("4x"))
    {
         mNationalInstruments->nPulseDelay4x = pulsedelay;
         mNationalInstruments->dFastBlankDelay4x = dFastDelay;
         mNationalInstruments->dFastFreq4x = dFastFreq;
     }
    if(arg1 == QString("8x"))
    {
         mNationalInstruments->nPulseDelay8x = pulsedelay;
         mNationalInstruments->dFastBlankDelay8x = dFastDelay;
         mNationalInstruments->dFastFreq8x = dFastFreq;
     }
    if(arg1 == QString("16x"))
    {
         mNationalInstruments->nPulseDelay16x = pulsedelay;
         mNationalInstruments->dFastBlankDelay16x = dFastDelay;
         mNationalInstruments->dFastFreq16x = dFastFreq;
     }
    if(arg1 == QString("32x"))
    {
         mNationalInstruments->nPulseDelay32x = pulsedelay;
         mNationalInstruments->dFastBlankDelay32x = dFastDelay;
         mNationalInstruments->dFastFreq32x = dFastFreq;
     }
    if(arg1 == QString("64x"))
    {
         mNationalInstruments->nPulseDelay64x = pulsedelay;
     }

    return;
}


void MainWindow::on_radioButton_toggled(bool checked)
{
    if(checked)
        MoveFirgelli(1,0);
}



void MainWindow::on_radioButton_2_toggled(bool checked)
{
    if(checked)
        MoveFirgelli(0,0);
}


void MainWindow::on_motionscale_dial_valueChanged(int value)
{
    if(this->bInitialized)
    mTrinamic->SetCoarseFineSetting(value);
}

void MainWindow::on_pushButton_relativeorigin_clicked()
{
    mTrinamic->SetRelativeModeOrigin();
    QString temp;
    temp.sprintf("(%.2f,%.2f,%.2f)",
                 mTrinamic->RelativeModeOrigin[0],
                 mTrinamic->RelativeModeOrigin[1],
                 mTrinamic->RelativeModeOrigin[2]);
    ui->label_relativeorigin->setText(temp);
}

void MainWindow::on_radioButton_relativemode_clicked(bool checked)
{
    mTrinamic->SetToRelativeMode();
}

void MainWindow::on_radioButton_absolutemode_clicked()
{
    mTrinamic->SetToAbsoluteMode();
}

void MainWindow::on_pushButton_acquirezstack_clicked()
{
    //external stack
    this->AcquireZStack(ui->doubleSpinBox_micronperslice->value(), ui->spinBox_totalzslices->value());
}

void MainWindow::on_pushButtonMonitor_clicked()
{

    if(!mMatroxImagingLibrary->bMonitoring)
    {
        StartMonitor();
    }
    else
    {
        if(bAcquiringStack)
        {
            StopZStack();
        }
        else
        {
            StopMonitor();
        }
    }
}

void MainWindow::on_pushButtonAcquire_clicked()
{
    if(!mMatroxImagingLibrary->bAcquiring)
    {
        StartAcquire();
    }
    else
    {
        StopAcquire();
    }
}

void MainWindow::on_checkBox_savemonitor_clicked()
{

    mMatroxImagingLibrary->bSaveMonitor = ui->checkBox_savemonitor->isChecked();
}

void MainWindow::on_checkBox_exttrigger_clicked()
{
    mMatroxImagingLibrary->bExtTrigger = ui->checkBox_exttrigger->isChecked();

}


void MainWindow::on_spinBox_extrazoom_editingFinished()
{

}

void MainWindow::on_checkBox_fastblank_clicked()
{

}

void MainWindow::on_checkBox_slowblank_clicked()
{

}

void MainWindow::on_checkBox_fovpower_clicked()
{

}

void MainWindow::on_checkBox_disablescanner_clicked()
{

    //mNationalInstruments->bResonantScanning = !(ui->checkBox_disablescanner->isChecked());

    QDebug(QtDebugMsg) << "Toggle resonant scanner\n";
    //box unchecked, start scanning
    if(!mNationalInstruments->bResonantScanning)
    {
        //turn on scanner
        mNationalInstruments->SetResonantScannerSelectBits(0, 0, 1);
        mNationalInstruments->StartResonantScanning();
        ui->pushButtonAcquire->setDisabled(false);
        ui->pushButtonMonitor->setDisabled(false);
    }
    //box checked, stop scanning
    else
    {
        mNationalInstruments->StopResonantScanning();
        //turn off scanner
        mNationalInstruments->SetResonantScannerSelectBits(0, 0, 0);
        ui->pushButtonAcquire->setDisabled(true);
        ui->pushButtonMonitor->setDisabled(true);
    }

}

void MainWindow::on_spinBox_sumframes_editingFinished()
{

}

void MainWindow::on_spinBox_sumpixels_editingFinished()
{

}

/*
void MainWindow::on_horizontalSlider_fastzoom_valueChanged(int value)
{
    //mNationalInstruments->dXScanFraction = double(value)/100.0;

    //double fast = double(ui->horizontalSlider_fastzoom->value())/100.0;
    //double slow = double(ui->horizontalSlider_slowzoom->value())/100.0;
    //UpdateZoom(fast, slow);
}

void MainWindow::on_horizontalSlider_slowzoom_valueChanged(int value)
{
    //mNationalInstruments->dYScanFraction = double(value)/100.0;

    //double fast = double(ui->horizontalSlider_fastzoom->value())/100.0;
    //double slow = double(ui->horizontalSlider_slowzoom->value())/100.0;
    //UpdateZoom(fast, slow);
}
*/

void MainWindow::on_checkBoxMedian_clicked(bool checked)
{
    mMatroxImagingLibrary->bMedianConvolve = checked;
}

void MainWindow::on_checkBoxMean_clicked(bool checked)
{

    mMatroxImagingLibrary->bMeanConvolve = checked;
}

void MainWindow::on_checkBoxInvert_clicked(bool checked)
{

    mMatroxImagingLibrary->bInvert = checked;
}

void MainWindow::on_checkBoxLog_clicked(bool checked)
{

    mMatroxImagingLibrary->bLog = checked;
}

void MainWindow::on_spinBox_sumframes_valueChanged(int arg1)
{

    mMatroxImagingLibrary->nSummationTotal = arg1;
    mMatroxImagingLibrary->UserHookData.nSummationTotal = arg1;
    mMatroxImagingLibrary->UpdateLUT();
}

void MainWindow::on_spinBox_sumpixels_valueChanged(int arg1)
{

    mMatroxImagingLibrary->nHorizontalDownsample = arg1;
}

void MainWindow::on_doubleSpinBox_fastzoom_valueChanged(double arg1)
{

    double fast = ui->doubleSpinBox_fastzoom->value();
    double slow = ui->doubleSpinBox_slowzoom->value();
    UpdateZoom(fast, slow, ui->doubleSpinBox_laserpower->value());
}

void MainWindow::on_doubleSpinBox_slowzoom_valueChanged(double arg1)
{

    double fast = ui->doubleSpinBox_fastzoom->value();
    double slow = ui->doubleSpinBox_slowzoom->value();
    UpdateZoom(fast, slow,ui->doubleSpinBox_laserpower->value());
}

void MainWindow::on_checkBox_savemonitor_clicked(bool checked)
{

}

void MainWindow::on_checkBox_exttrigger_clicked(bool checked)
{
    mMatroxImagingLibrary->bExtTrigger = checked;
}

void MainWindow::on_checkBox_retriggerable_clicked(bool checked)
{
    mMatroxImagingLibrary->bRetrigger = checked;
}

void MainWindow::on_spinBox_frames_valueChanged(int arg1)
{
    mMatroxImagingLibrary->nFramesPerFile = arg1;

}

void MainWindow::on_comboBox_linesperframe_currentIndexChanged(const QString &arg1)
{
    printf("Changing lines per frame.\n");

    if(!bResonantScanning)
    {
        return;
    }

    //this sets the lines per frame for writing to DCF
    mMatroxImagingLibrary->nDesiredLinesPerFrame = arg1.toInt();

    //it should turn out that the DCF will match this
    mNationalInstruments->nLinesPerFrame = arg1.toInt();

    mMatroxImagingLibrary->Shutdown();
    mMatroxImagingLibrary->Initialize();
    //fixes bug "can't see image on changing lines per frame"
    mMatroxImagingLibrary->UpdateLUT();
    //mMatroxImagingLibrary->UpdateLUT();
    mMatroxImagingLibrary->UpdateGain();
    mMatroxImagingLibrary->UpdateCouplingMode();

    //reset scanners if we're scanning
    if(mNationalInstruments->bResonantScanning)
    {
        mNationalInstruments->StopResonantScanning();
        mNationalInstruments->StartResonantScanning();
    }

    ui->doubleSpinBox_framerate->setValue(
                mMatroxImagingLibrary->dFramerate);

}

void MainWindow::on_spinBox_pulsedelay_valueChanged(int arg1)
{
    mNationalInstruments->nPulseDelay = arg1;

    SaveDelay();

    if(mNationalInstruments->bResonantScanning)
    {
        mNationalInstruments->ResetHSync();
    }
}

void MainWindow::on_spinBox_min_1_valueChanged(int arg1)
{
    mMatroxImagingLibrary->nMin[0] = arg1;
        mMatroxImagingLibrary->UpdateLUT();
}

void MainWindow::on_spinBox_max_1_valueChanged(int arg1)
{

    mMatroxImagingLibrary->nMax[0] = arg1;
        mMatroxImagingLibrary->UpdateLUT();
}
void MainWindow::on_spinBox_min_2_valueChanged(int arg1)
{
    mMatroxImagingLibrary->nMin[1] = arg1;
        mMatroxImagingLibrary->UpdateLUT();
}

void MainWindow::on_spinBox_max_2_valueChanged(int arg1)
{

    mMatroxImagingLibrary->nMax[1] = arg1;
        mMatroxImagingLibrary->UpdateLUT();
}
void MainWindow::on_spinBox_min_3_valueChanged(int arg1)
{
    mMatroxImagingLibrary->nMin[2] = arg1;
        mMatroxImagingLibrary->UpdateLUT();
}

void MainWindow::on_spinBox_max_3_valueChanged(int arg1)
{

    mMatroxImagingLibrary->nMax[2] = arg1;
        mMatroxImagingLibrary->UpdateLUT();
}
void MainWindow::on_spinBox_min_4_valueChanged(int arg1)
{
    mMatroxImagingLibrary->nMin[3] = arg1;
        mMatroxImagingLibrary->UpdateLUT();
}

void MainWindow::on_spinBox_max_4_valueChanged(int arg1)
{

    mMatroxImagingLibrary->nMax[3] = arg1;
        mMatroxImagingLibrary->UpdateLUT();
}

void MainWindow::on_checkBox_rotationmode_clicked(bool checked)
{
    mTrinamic->bRotationMode = checked;
    UpdateInterface();
}

void MainWindow::on_doubleSpinBox_objectiveangle_valueChanged(double arg1)
{
    mTrinamic->XZRotationAngle = arg1/180.0*3.1415926;
}

void MainWindow::fnChangeFocus(QWidget* a,QWidget* b)
{
    OnLoseFocus();
}

void MainWindow::OnLoseFocus()
{
    if(this->bAcquiringStack | bAcquiringStack_Precise | bAcquiringStack_Fast |
            this->bWaitingForLastFinish)
    {
        printf("Ignoring focus out due to script cmd.\n");
        return;
    }
    printf("Losing focus, stop motors.\n");

    if(bTrinamic && this->bInitialized)
        mTrinamic->StopMotors();


    /*
    //this->focuso
    //this->setWindowFlags(Qt::WindowStaysOnTopHint);
    //this->setWindowFlags(Qt::WindowActive);
    this->setFocus();
    this->setWindowState(Qt::WindowActive);
    this->activateWindow();
    this->show();
    this->grabKeyboard();
    */
    return;
}

void MainWindow::focusOutEvent(QFocusEvent* e)
{

    OnLoseFocus();

    QMainWindow::focusOutEvent(e);

}

//void MainWindow::OnKeyPressed(byte* keysDepressed, int vkCode);
void MainWindow::OnKeyPressed(QKeyEvent* e, bool pressed)
{

    //QDebug(QtDebugMsg) << "Caught global event." << endl;

    this->HandleKeyboardEvent(e, pressed, true);

    return;
}


void MainWindow::on_actionExit_triggered()
{
    printf("Exit event, starting close.\n");
    printf("Close event - shutting down...\n");
    this->Shutdown();
    this->close();
}

void MainWindow::closeEvent(QCloseEvent * e)
{

    printf("Close event - shutting down...\n");
    this->Shutdown();
}

void MainWindow::on_checkBoxSine_clicked(bool checked)
{
    mMatroxImagingLibrary->bWarp = checked;
    mMatroxImagingLibrary->FillHookDataStruct();
}

void  MainWindow::OnShuttleMoved(DWORD event, UCHAR status, WORD type, WORD devicenumber)
{
    int motor = 0;

    /*
        switch(type)
        {
        case SHUTTLEXPRESS:
                printf("ShuttleXpress ");
                break;
        case SHUTTLEPRO:
                printf("ShuttlePro    ");
                break;
        case SHUTTLEPRO2:
                printf("ShuttlePro2   ");
                break;
        default:
                printf("Shuttle?      ");
        }
        */

        switch(devicenumber)
        {
        case SHUTTLEPRIMARY:
                //printf("(1) ");
                motor = mTrinamic->XMotor;
                break;
        case SHUTTLESECONDARY:
                //printf("(2) ");
                motor = mTrinamic->YMotor;
                break;
        default:
                printf("(?) ");
                break;
        }

        if((event>=SHUTTLEEVENTSHUTTLEFIRST)&&(event<=SHUTTLEEVENTSHUTTLELAST))
        {
                //printf(" Shuttle ");
                if(status)
                {
                    //printf("enters ");
                    mTrinamic->SetVelocityBin(motor, int(event-SHUTTLEEVENTSHUTTLE)/2, 0);
                    return;
                }
                //else printf("exits ");
                printf("zone %d", event-SHUTTLEEVENTSHUTTLE);
        }

        if((event>=SHUTTLEEVENTBUTTONFIRST)&&(event<=SHUTTLEEVENTBUTTONLAST))
        {
                if(status)
                {
                     printf(" Button %d", event-SHUTTLEEVENTBUTTON);
                     printf(" pressed");
                     int newvalue = mTrinamic->CurrentCoarseFineSetting;
                     if(event == SHUTTLEEVENTBUTTON4)
                         newvalue--;
                     if(event == SHUTTLEEVENTBUTTON8)
                         newvalue++;

                     newvalue = max(newvalue,ui->motionscale_dial->minimum());
                     newvalue = min(newvalue,ui->motionscale_dial->maximum());

                     mTrinamic->SetCoarseFineSetting(newvalue);
                     ui->motionscale_dial->setValue(newvalue);
                     printf("Motion scale %d", newvalue);
                }
                //else printf(" released");
        }

        if((event>=SHUTTLEEVENTJOGFIRST)&&(event<=SHUTTLEEVENTJOGLAST))
        {
                if(status)
                {
                    //previous activation time based rate limit
                    //DWORD Timeout=GetTickCount();


                        printf(" Jog\n");
                        switch(event)
                        {
                        case SHUTTLEEVENTJOGLEFT:
                                //printf("left");
                                mTrinamic->TakeStrides(mTrinamic->ZMotor, 6, 0);
                            break;
                        case SHUTTLEEVENTJOGRIGHT:
                                //printf("right");
                                mTrinamic->TakeStrides(mTrinamic->ZMotor, -6, 0);
                                break;
                        }
                }
        }

        printf("\r");
}

void MainWindow::on_checkBoxColor_clicked(bool checked)
{
    mMatroxImagingLibrary->bColor = checked;
}

void MainWindow::on_lineEdit_dataset_editingFinished()
{
    UpdateFilename();
}

void MainWindow::on_reset_display_clicked()
{

    printf("Resetting display.\n");
    mMatroxImagingLibrary->Shutdown();
    mMatroxImagingLibrary->Initialize();
    mMatroxImagingLibrary->UpdateGain();
    mMatroxImagingLibrary->UpdateLUT();
    mMatroxImagingLibrary->UpdateCouplingMode();
}

void MainWindow::on_doubleSpinBox_gain1_valueChanged(double arg1)
{

    mMatroxImagingLibrary->dADCMax[0] = arg1;
    mMatroxImagingLibrary->UpdateGain();
}

void MainWindow::on_doubleSpinBox_gain2_valueChanged(double arg1)
{

    mMatroxImagingLibrary->dADCMax[1] = arg1;
    mMatroxImagingLibrary->UpdateGain();
}

void MainWindow::on_doubleSpinBox_gain3_valueChanged(double arg1)
{

    mMatroxImagingLibrary->dADCMax[2] = arg1;
    mMatroxImagingLibrary->UpdateGain();
}
void MainWindow::on_doubleSpinBox_gain1_2_valueChanged(double arg1)
{

    mMatroxImagingLibrary->dADCMin[0] = arg1;
    mMatroxImagingLibrary->UpdateGain();
}

void MainWindow::on_doubleSpinBox_gain2_2_valueChanged(double arg1)
{

    mMatroxImagingLibrary->dADCMin[1] = arg1;
    mMatroxImagingLibrary->UpdateGain();
}

void MainWindow::on_doubleSpinBox_gain3_2_valueChanged(double arg1)
{

    mMatroxImagingLibrary->dADCMin[2] = arg1;
    mMatroxImagingLibrary->UpdateGain();
}

//aggregate UI values for future code refactor
/*

    mMatroxImagingLibrary->nMin[0] = arg1;
    mMatroxImagingLibrary->nMax[3] = arg1;
    mMatroxImagingLibrary->bWarp = checked;
    mMatroxImagingLibrary->UserHookData.bWarp = checked;
    mMatroxImagingLibrary->bColor = checked;
    mMatroxImagingLibrary->nGain[1] = ui->spinBox_gain2->value();

  */



void MainWindow::on_checkBox_mono1_clicked(bool checked)
{
    mMatroxImagingLibrary->bCopyChannel[0] = checked;
    if(checked)
    {
        ui->checkBox_mono2->setChecked(false);
        mMatroxImagingLibrary->bCopyChannel[1] = false;
        ui->checkBox_mono3->setChecked(false);
        mMatroxImagingLibrary->bCopyChannel[2] = false;
    }
}

void MainWindow::on_checkBox_mono2_clicked(bool checked)
{
    mMatroxImagingLibrary->bCopyChannel[1] = checked;
    if(checked)
    {
        ui->checkBox_mono1->setChecked(false);
        mMatroxImagingLibrary->bCopyChannel[0] = false;
        ui->checkBox_mono3->setChecked(false);
        mMatroxImagingLibrary->bCopyChannel[2] = false;
    }
}

void MainWindow::on_checkBox_mono3_clicked(bool checked)
{
    mMatroxImagingLibrary->bCopyChannel[2] = checked;
    if(checked)
    {
        ui->checkBox_mono1->setChecked(false);
        mMatroxImagingLibrary->bCopyChannel[0] = false;
        ui->checkBox_mono2->setChecked(false);
        mMatroxImagingLibrary->bCopyChannel[1] = false;
    }

}

void MainWindow::on_doubleSpinBox_flyback_valueChanged(double arg1)
{
    mNationalInstruments->dYRampDutyCycle = 1.0 - arg1;



    if(mNationalInstruments->bResonantScanning)
    {
        printf("Restarting scanning\n");
        mNationalInstruments->StopResonantScanning();
        mNationalInstruments->StartResonantScanning();
    }
}

void MainWindow::on_checkBox_fastblank_clicked(bool checked)
{
    mNationalInstruments->bFastBlank = checked;
    if(mNationalInstruments->bResonantScanning)
    {
        printf("Restarting scanning\n");
    mNationalInstruments->StopResonantScanning();
    mNationalInstruments->StartResonantScanning();
    }
}

void MainWindow::on_checkBox_slowblank_clicked(bool checked)
{
    mNationalInstruments->bSlowBlank = checked;
    if(mNationalInstruments->bResonantScanning)
    {
        printf("Restarting scanning\n");
    mNationalInstruments->StopResonantScanning();
    mNationalInstruments->StartResonantScanning();
    }
}

void MainWindow::on_doubleSpinBox_laserpower_valueChanged(double arg1)
{
    mNationalInstruments->dLaserPower = arg1;
    if(mNationalInstruments->bResonantScanning)
    {
        printf("Restarting scanning\n");
    mNationalInstruments->StopResonantScanning();
    mNationalInstruments->StartResonantScanning();
    }
}

void MainWindow::on_lineEdit_pathname_editingFinished()
{

    UpdateFilename();
}

void MainWindow::on_checkBoxAC_clicked(bool checked)
{
    mMatroxImagingLibrary->bACCoupling = checked;
    mMatroxImagingLibrary->UpdateCouplingMode();
}

void MainWindow::on_checkBox_showoverlay_clicked(bool checked)
{
    mMatroxImagingLibrary->bOverlay = checked;
}

void MainWindow::on_checkBox_showframenumber_clicked(bool checked)
{
    mMatroxImagingLibrary->bOvFramenumber = checked;
}

void MainWindow::on_checkBox_showposition_clicked(bool checked)
{
    mMatroxImagingLibrary->bOvPosition = checked;
}

void MainWindow::on_checkBox_showcrosshairs_clicked(bool checked)
{
    mMatroxImagingLibrary->bOvCrosshairs = checked;
}

void MainWindow::on_checkBox_showscalebars_clicked(bool checked)
{
    mMatroxImagingLibrary->bOvScalebars = checked;
}

void MainWindow::on_checkBox_showexposure_clicked(bool checked)
{
    mMatroxImagingLibrary->bOvExposure = checked;
}

void MainWindow::on_checkBox_showoverlayimage_clicked(bool checked)
{
    mMatroxImagingLibrary->bOvOverlayImage = checked;
}

void MainWindow::on_pushButton_savedisplaytooverlay_clicked()
{
    mMatroxImagingLibrary->SaveCurrentImageOverlay();
}

void MainWindow::on_pushButton_depthstart_clicked()
{
    dPreciseStackStart = mTrinamic->CurrentPositionRotated[mTrinamic->ZMotor];
    printf("Precise stack start (um): %f \n", dPreciseStackStart);
    ui->doubleSpinBox_depthstart->setValue(ui->lcdNumber_Z->value());
    UpdatePreciseStack();
}

void MainWindow::on_pushButton_depthend_clicked()
{
    dPreciseStackFinish = mTrinamic->CurrentPositionRotated[mTrinamic->ZMotor];
    printf("Precise stack finish (um): %f \n", dPreciseStackFinish);
    ui->doubleSpinBox_depthend->setValue(ui->lcdNumber_Z->value());
    UpdatePreciseStack();
}

void MainWindow::on_doubleSpinBox_depthstart_valueChanged(double arg1)
{

}

void MainWindow::on_doubleSpinBox_depthend_valueChanged(double arg1)
{

}

void MainWindow::on_doubleSpinBox_micronperslice_2_valueChanged(double arg1)
{

}

void MainWindow::on_doubleSpinBox_powerstart_valueChanged(double arg1)
{

}

void MainWindow::on_doubleSpinBox_powerend_valueChanged(double arg1)
{

}

void MainWindow::on_doubleSpinBox_lengthscale_valueChanged(double arg1)
{

}

void MainWindow::on_pushButton_fastzstack_clicked()
{
    if(bResonantScanning)
    {
        if(!bAcquiringStack_Fast)
        {
            if(bStackPreciseReady)
            {
                //start precise stack
                this->Acquire3DMosaicFast(
                            1,
                            1,
                            this->dPreciseStackStart,
                            this->dPreciseStackFinish,
                            0.0, 0.0,
                            ui->spinBox_fastzspeed->value(),
                            ui->doubleSpinBox_powerstart->value(),
                            ui->doubleSpinBox_powerend->value());

                bAcquiringStack_Fast = true;
            }
        }
        else
        {
            this->StopZStack_Precise();
        }
    }
}

void MainWindow::on_pushButton_precisezstack_clicked()
{

    if(bResonantScanning)
    {
        if(!bAcquiringStack_Precise)
        {
            if(bStackPreciseReady)
            {
                //start precise stack
                AcquireZStack_Precise(0,0);
                bAcquiringStack_Precise = true;
            }
            //ui->pushButton_precisezstack->setDisabled(0);
            //ui->pushButton_precisezstack->setText(QString(''));
        }
        else
        {
            //we are acquiring precise stack
            //if clicked, abort
            this->StopZStack_Precise();
        }
    }

}

void MainWindow::on_spinBox_imagesx_valueChanged(int arg1)
{

}

void MainWindow::on_spinBox_imagesy_valueChanged(int arg1)
{

}

void MainWindow::on_doubleSpinBox_stridex_valueChanged(double arg1)
{

}

void MainWindow::on_doubleSpinBox_stridey_valueChanged(double arg1)
{

}

void MainWindow::on_pushButton_mosaic2d_clicked()
{

    if(!bAcquiringMosaic)
    {
        Acquire2DMosaic(ui->spinBox_imagesx->value(),
                        ui->spinBox_imagesy->value(),
                        ui->doubleSpinBox_stridex->value(),
                        ui->doubleSpinBox_stridey->value()
                        );
    }
    else
    {
        StopMosaic();
    }

}

void MainWindow::on_comboBox_magnification_currentIndexChanged(const QString &arg1)
{
    int mag = 1;
    int pulsedelay = mNationalInstruments->nPulseDelay;
    double dFastDelay, dFastFreq;
    if(arg1 == QString("1x"))
    {
        mag = 1;
        pulsedelay = mNationalInstruments->nPulseDelay1x;
        dFastDelay = mNationalInstruments->dFastBlankDelay1x;
        dFastFreq = mNationalInstruments->dFastFreq1x;
    }
    if(arg1 == QString("2x"))
    {
         mag = 2;
         pulsedelay = mNationalInstruments->nPulseDelay2x;
         dFastDelay = mNationalInstruments->dFastBlankDelay2x;
         dFastFreq = mNationalInstruments->dFastFreq2x;
     }
    if(arg1 == QString("4x"))
    {
         mag = 4;
         pulsedelay = mNationalInstruments->nPulseDelay4x;
         dFastDelay = mNationalInstruments->dFastBlankDelay4x;
         dFastFreq = mNationalInstruments->dFastFreq4x;
     }
    if(arg1 == QString("8x"))
    {
         mag = 8;
         pulsedelay = mNationalInstruments->nPulseDelay8x;
         dFastDelay = mNationalInstruments->dFastBlankDelay8x;
         dFastFreq = mNationalInstruments->dFastFreq8x;
     }
    if(arg1 == QString("16x"))
    {
         mag = 16;
         pulsedelay = mNationalInstruments->nPulseDelay16x;
         dFastDelay = mNationalInstruments->dFastBlankDelay16x;
         dFastFreq = mNationalInstruments->dFastFreq16x;
     }
    if(arg1 == QString("32x"))
    {
         mag = 32;
         pulsedelay = mNationalInstruments->nPulseDelay32x;
         dFastDelay = mNationalInstruments->dFastBlankDelay32x;
         dFastFreq = mNationalInstruments->dFastFreq32x;
     }
    if(arg1 == QString("64x"))
    {
         mag = 64;
         pulsedelay = mNationalInstruments->nPulseDelay64x;
     }

    SetMagnification(mag);

    mNationalInstruments->nPulseDelay = pulsedelay;
    mNationalInstruments->dFastFreq = dFastFreq;
    mNationalInstruments->dFastBlankDelay = dFastDelay;

    ui->spinBox_pulsedelay->setValue(pulsedelay);
    ui->doubleSpinBox_fastdelay->setValue(dFastDelay);
    ui->doubleSpinBox_fastfreq->setValue(dFastFreq);

    mNationalInstruments->ResetHSync();

}

void MainWindow::on_checkBox_showrois_clicked(bool checked)
{
    mMatroxImagingLibrary->bOvLiveGrid = checked;
}

void MainWindow::on_actionAnalysis_Window_triggered(bool checked)
{
    if(checked) pw->show();
    else pw->hide();
    ui->checkBox_showanalysis->setChecked(checked);
}

void MainWindow::on_checkBox_showanalysis_clicked(bool checked)
{
    if(checked) pw->show();
    else pw->hide();
    ui->actionAnalysis_Window->setChecked(checked);
}

void MainWindow::on_checkBox_computeroitraces_clicked(bool checked)
{
    mMatroxImagingLibrary->bCompTraces = checked;

}

void MainWindow::on_checkBox_computehistograms_clicked(bool checked)
{
    mMatroxImagingLibrary->bCompHistograms = checked;
}



//Save pulse delay setting for given mag
void MainWindow::on_pushButton_savedelay_clicked()
{
    SaveDelay();
}

void MainWindow::on_spinBox_clockmult_valueChanged(int arg1)
{
    printf("Changing clock multiplier\n");
    if(!bMatrox) return;

    if(!mMatroxImagingLibrary->bAcquiring && !mMatroxImagingLibrary->bMonitoring)
    {
        mMatroxImagingLibrary->nClockMultiplier = arg1;
        mMatroxImagingLibrary->Shutdown();
        mMatroxImagingLibrary->Initialize();
        mMatroxImagingLibrary->UpdateGain();
        mMatroxImagingLibrary->UpdateLUT();
        mMatroxImagingLibrary->UpdateCouplingMode();
    }
}

void MainWindow::on_checkBox_acquirepreview_clicked(bool checked)
{
    mMatroxImagingLibrary->bAcquirePreview = checked;
}

void MainWindow::on_spinBox_totalzslices_precise_valueChanged(int arg1)
{
    UpdatePreciseStack();
}

void MainWindow::on_spinBox_fragmentsize_valueChanged(int arg1)
{

    mMatroxImagingLibrary->nFragmentSize = arg1;
}

void MainWindow::on_checkBox_fragment_clicked(bool checked)
{
    mMatroxImagingLibrary->bFragment = checked;
}

void MainWindow::on_pushButton_clicked()
{
    //fileName = QFileDialog::getOpenFileName(this,
    //     tr("Choose directory"), mMatroxImagingLibrary->sFilepath, tr("Choose path"));

    printf("Choose directory\n");
    QFileDialog dialog(this);
    //dialog.set
    dialog.setFileMode(QFileDialog::Directory);
    dialog.setOption(QFileDialog::ShowDirsOnly, true);

    dialog.setDirectory(mMatroxImagingLibrary->sFilepath);
    QStringList fileNames;

     if (dialog.exec())
     {
         fileNames = dialog.selectedFiles();
         ui->lineEdit_pathname->setText(fileNames.first() + '/');
         UpdateFilename();
     }

}

void MainWindow::on_pushButtonZeroAcq_clicked()
{
    mMatroxImagingLibrary->nAcquisitionNumber = 0;
    mMatroxImagingLibrary->UpdateFilename();
    UpdateInterface();
    UpdateFilenameToUi();
}

void MainWindow::on_comboBox_linesperframe_currentIndexChanged(int index)
{

}

void MainWindow::on_pushButton_mosaic3d_clicked()
{
    if(!bAcquiringMosaic)
    {

        Acquire3DMosaic(ui->spinBox_imagesx->value(),
                        ui->spinBox_imagesy->value(),
                        ui->spinBox_totalzslices_precise->value(),
                        ui->doubleSpinBox_stridex->value(),
                        ui->doubleSpinBox_stridey->value(),
                        ui->doubleSpinBox_micronperslice_2->value(),
                        ui->doubleSpinBox_powerstart->value(),
                        ui->doubleSpinBox_powerend->value()
                        );
    }
    else
    {
        StopMosaic();
    }

}

void MainWindow::on_pushButton_mosaic3d_fast_clicked()
{
    if(!bAcquiringMosaic)
    {

        Acquire3DMosaicFast(ui->spinBox_imagesx->value(),
                        ui->spinBox_imagesy->value(),
                        this->dPreciseStackStart,
                        this->dPreciseStackFinish,
                        ui->doubleSpinBox_stridex->value(),
                        ui->doubleSpinBox_stridey->value(),
                        ui->spinBox_fastzspeed->value(),
                        ui->doubleSpinBox_powerstart->value(),
                        ui->doubleSpinBox_powerend->value()
                        );
    }
    else
    {
        StopMosaic();
    }

    return;
}

void MainWindow::on_checkBox_save1_clicked(bool checked)
{
    mMatroxImagingLibrary->bSaveChannel[0] = checked;
}

void MainWindow::on_checkBox_save2_clicked(bool checked)
{
    mMatroxImagingLibrary->bSaveChannel[1] = checked;
}

void MainWindow::on_checkBox_save3_clicked(bool checked)
{
    mMatroxImagingLibrary->bSaveChannel[2] = checked;
}

void MainWindow::on_doubleSpinBox_fastfreq_valueChanged(double arg1)
{
    if(this->bResonantScanning)
    {

        mNationalInstruments->dFastFreq = arg1;

        if(mNationalInstruments->bResonantScanning)
        {
            mNationalInstruments->StopResonantScanning();
            mNationalInstruments->StartResonantScanning();
        }
    }
}

void MainWindow::on_checkBox_sumacquire_clicked(bool checked)
{
    mMatroxImagingLibrary->bSumAcquire = checked;
}

void MainWindow::on_checkBox_stoptrigger_clicked(bool checked)
{
    mMatroxImagingLibrary->bStopTrigger = checked;
}

void MainWindow::on_checkBox_lockadc_clicked(bool checked)
{
    mMatroxImagingLibrary->bLockADC = checked;
}

void MainWindow::on_actionManual_triggered()
{
    Manual * myman = new Manual(this);
    myman->show();
}

void MainWindow::on_checkBox_lockfast_clicked(bool checked)
{
     ui->fastblanktune->setDisabled(checked);
     ui->slowblanktune->setDisabled(checked);
}


void MainWindow::on_doubleSpinBox_fastdelay_valueChanged(double arg1)
{

    if(this->bResonantScanning)
    {

        mNationalInstruments->dFastBlankDelay = arg1;

        if(mNationalInstruments->bResonantScanning)
        {
            mNationalInstruments->StopResonantScanning();
            mNationalInstruments->StartResonantScanning();
        }
    }
}

void MainWindow::on_doubleSpinBox_fastwidth_valueChanged(double arg1)
{

    if(this->bResonantScanning)
    {

        mNationalInstruments->dFastBlankWidth = arg1;

        if(mNationalInstruments->bResonantScanning)
        {
            mNationalInstruments->StopResonantScanning();
            mNationalInstruments->StartResonantScanning();
        }
    }
}

void MainWindow::on_doubleSpinBox_slowwidth_valueChanged(double arg1)
{

    if(this->bResonantScanning)
    {

        mNationalInstruments->dSlowBlankWidth = arg1;

        if(mNationalInstruments->bResonantScanning)
        {
            mNationalInstruments->StopResonantScanning();
            mNationalInstruments->StartResonantScanning();
        }
    }
}

void MainWindow::on_doubleSpinBox_slowdelay_valueChanged(double arg1)
{

    if(this->bResonantScanning)
    {

        mNationalInstruments->dSlowBlankDelay = arg1;

        if(mNationalInstruments->bResonantScanning)
        {
            mNationalInstruments->StopResonantScanning();
            mNationalInstruments->StartResonantScanning();
        }
    }
}

void MainWindow::on_checkBox_monitormerge_clicked(bool checked)
{
    mMatroxImagingLibrary->bChannelMerge = checked;
}

void MainWindow::on_spinBox_fastzspeed_valueChanged(int arg1)
{

}

void MainWindow::on_checkBoxSine_rawcprocessing_clicked(bool checked)
{
    mMatroxImagingLibrary->bRawCProcessing = checked;
}

void MainWindow::on_checkBox_motorizedrotation_clicked(bool checked)
{
    mTrinamic->bMotorizedRotation = checked;
    UpdateInterface();
}

void MainWindow::on_pushButton_zeroangle_clicked()
{
    mTrinamic->SetMotorizedRotationOrigin();
    UpdateInterface();
}

void MainWindow::on_doubleSpinBox_radius_valueChanged(double arg1)
{
    mTrinamic->PivotRadius = arg1;
}

void MainWindow::on_checkBox_fastprocess_clicked(bool checked)
{
    mMatroxImagingLibrary->bBareTransform = checked;
}

void MainWindow::on_checkBox_flipx_clicked(bool checked)
{
    mMatroxImagingLibrary->bFlipX = checked;
}

void MainWindow::on_checkBox_flipy_clicked(bool checked)
{
    mMatroxImagingLibrary->bFlipY = checked;
}

void MainWindow::on_pushButton_retract_clicked()
{
    Retract();
}

void MainWindow::on_pushButton_lasercalibration_clicked()
{
    LoadPowerCalibration();
}
